Qu'est-ce que le test unitaire boîte noire?

11

J'ai récemment passé mon examen final pour un cours de génie logiciel pour mon programme de maîtrise et l'une des questions de l'examen était la suivante:

Unit Testing is considered:
a. White-box Testing
b. Black-box Testing
c. Either

Au cours de mes 7 années d'expérience en développement de logiciels, les tests unitaires ont toujours adopté une approche en boîte blanche. Le testeur a toujours eu une connaissance complète de la mise en œuvre de l'unité lors de la rédaction des tests. Les tests de la boîte noire sont toujours venus plus tard sous la forme de tests d'intégration, de système et d'acceptation.

Cependant, la bonne réponse à l'examen (selon le professeur) est que les tests unitaires peuvent être des tests en boîte blanche ou noire.

J'ai fait quelques recherches, et il semble que de nombreux cas "tests unitaires de boîte noire" sont utilisés pour décrire une approche test-first où les tests unitaires sont écrits avant le code. Cependant, à mon avis, il s'agit toujours de tests en boîte blanche. Bien que l'implémentation n'existe pas encore, celui qui écrit le test a généralement une assez bonne idée de la façon dont le code source va être implémenté.

Quelqu'un peut-il m'expliquer comment fonctionnent les tests unitaires en boîte noire (si c'est vraiment une chose) et en quoi ils diffèrent des tests unitaires en boîte blanche?

backcab
la source
4
comment le professeur a-t-il clarifié cela lorsque vous leur avez posé des questions à ce sujet? (voir aussi Pourquoi les questions d'entrevue rendent-elles les questions de Software Engineering.SE médiocres? )
gnat
"celui qui écrit le test a généralement une assez bonne idée de la façon dont le test sera mis en œuvre" - il ne s'agit pas de savoir si vous savez comment le test est mis en œuvre, mais si vous savez (blanc) ou non (noir) comment la chose que vous testez est implémenté.
Jesper
@Jesper désolé. Je voulais dire "comment le code source va être implémenté". Je l'ai corrigé dans la question.
backcab
2
While the implementation does not yet exist, whoever is writing the test generally has a pretty good idea about how the source code is going to be implemented.- Oui, mais pas le test lui - même . Le test en boîte blanche signifie tester quelque chose interne à la méthode ou à la classe, comme la valeur d'une variable. Cela ne signifie pas que l'auteur du test sait à quoi ressemble le code testé.
Robert Harvey
1
Associé, pourrait être considéré comme un doublon: TDD utilise-t
Doc Brown

Réponses:

20

Votre professeur a raison: les tests unitaires peuvent être en boîte noire ou en boîte blanche. La différence est moins sur ce que le testeur sait, mais plus sur la façon dont vous générez des cas de test.

Avec les tests de boîte noire, vous ne regardez que l'interface et (si elle existe) la spécification d'un composant. Lorsqu'une fonction a une signature int foo(int a, int b), je peux immédiatement générer quelques cas de test juste en testant des entiers intéressants: zéro, un, moins un, des nombres à plusieurs chiffres, INT_MAX, INT_MAX - 1 et ainsi de suite. Les tests de boîte noire sont excellents car ils sont indépendants de la mise en œuvre. Mais ils pourraient aussi manquer des cas importants.

Avec un test en boîte blanche, je regarde l'implémentation, c'est-à-dire le code source et j'en génère des cas de test. Par exemple, je pourrais vouloir atteindre une couverture de chemin de 100% pour une fonction. Je choisis ensuite les valeurs d'entrée pour que tous les chemins soient empruntés. Les tests en boîte blanche sont excellents car ils peuvent exercer de manière exhaustive un morceau de code, avec beaucoup plus de confiance qu'un test en boîte noire. Mais ils pourraient ne tester que les détails de l'implémentation, pas un comportement réellement important. Dans certains cas, ils sont clairement une perte de temps.

Puisqu'un test en boîte blanche est dérivé de l'implémentation, il ne peut être écrit qu'après. Un test de boîte noire est dérivé de la conception / interface / spécification et peut donc être écrit avant ou après la mise en œuvre. TDD n'est ni clairement une boîte noire ni une boîte blanche. Étant donné que tout comportement est d'abord exprimé par un test, puis que le code minimal pour ce comportement est implémenté, TDD aboutit à des cas de test similaires à un test de boîte blanche. Mais quand on regarde le flux d'informations, les tests TDD ne sont pas dérivés du code source, mais d'exigences externes. Par conséquent, TDD ressemble plus à une boîte noire.

amon
la source
3
"Puisqu'un test de boîte blanche est dérivé de l'implémentation, il ne peut être écrit qu'après" - eh bien, si je vais écrire un test d'échec dans le style TDD pour la prochaine nouvelle fonctionnalité que j'aime ajouter à ma fonction ou classe existante , J'examine d'abord l'implémentation actuelle pour savoir ce qui n'est pas pris en charge jusqu'à présent, afin de pouvoir concevoir un test plus significatif - initialement défaillant -. J'appelle cela une approche de boîte blanche test-first, pas un test écrit par la suite. (Néanmoins, +1 de moi).
Doc Brown
4

Si vous entreprenez un développement piloté par les tests, alors en théorie, tous vos tests unitaires devraient être une boîte noire. C'est votre "approche test-first". Vous écrivez le contrat (interface), écrivez les tests pour ce contrat, puis le contrat est rempli par l'implémentation. Le test ne sait donc rien et ne devrait rien savoir de la mise en œuvre.

Après tout, lorsque vous écrivez un test, que testez-vous? Méthodes / fonctions publiques.

Si vous deviez écrire l'interface pour une classe, puis écrire les tests, et ensuite vous êtes frappé par un bus, le gars qui écrit la classe pendant que vous êtes à l'hôpital devrait pouvoir le faire à partir de votre interface, non? Il ne devrait pas avoir à le jeter et à écrire sa propre interface et ses propres tests.

Lorsque cela se désagrège quelque peu, c'est quand vous devez vous moquer de quelque chose dont la mise en œuvre dépend, mais si vous vous trouvez dans la situation où vous vous moquez de quelque chose qui n'est jamais exposé publiquement, alors vous avez fait une erreur, et vous devez voir Dependency Injection et al . Par conséquent, je dirais que les tests unitaires en boîte blanche, et non le noir, devraient être l'exception.

Considérez «Test sur les toilettes - Le comportement du test n'est pas implémenté» , dans lequel l'implémentation d'une classe est modifiée mais les tests doivent toujours être valides.

Cependant, si vous devez vous assurer que votre couverture de code est en place (c'est-à-dire que tous les chemins conditionnels sont testés dans l'implémentation), alors vous devrez absolument effectuer un test unitaire en boîte blanche, car la seule façon de savoir ce que votre les chemins sont en regardant les chemins dans l'implémentation.

AdamJS
la source
2
If you were to write the interface for a class, and then write the tests, and then you get hit by a bus, the guy who writes the class while you're in hospital should be able to do so from your interface, right?-- Pas exactement. La plupart des contrats d'API ne spécifient vraiment que les signatures de méthode, pas la sémantique ou le comportement.
Robert Harvey
Tu as raison; Je tenais pour acquis que votre interface inclurait la spécification à partir de laquelle elle a été écrite, et non pas simplement le texte de MyClassInterface.
AdamJS
@RobertHarvey, il est vrai que la plupart des interfaces ne décrivent pas explicitement la sémantique ou le comportement, mais je pense qu'il est généralement là implicitement. S'il n'était pas là, le code qui nécessite une certaine sémantique ne pourrait pas dépendre de l'abstraction. Et il n'y a rien pour arrêter les interfaces, y compris les détails de la sémantique et du comportement en tant que commentaires / docblocs. Par exemple, voir github.com/php-fig/http-message/blob/master/src/…
bdsl
3

Je dirais que tous les tests unitaires bien écrits sont intrinsèquement «boîte noire». Bien sûr, je pourrais avoir une implémentation à l'esprit lorsque j'écris le test, mais cette implémentation peut changer lorsque je refactorise. Le test ne doit donc utiliser que des API publiques pendant le test afin de tester la fonctionnalité, pas l'implémentation. Il ne se soucie pas des détails de mise en œuvre, donc ses tests de boîte noire.

Si j'écris des tests qui accèdent aux aspects internes ou privés de l'unité testée, alors je teste les détails d'implémentation: je suis un test en boîte blanche. Mais j'écris également des tests fragiles qui peuvent facilement se casser lorsque l'implémentation est modifiée. Ces tests en boîte blanche sont donc une mauvaise idée et doivent être évités.

Conclusion: si vous testez la boîte blanche avec des tests unitaires, vous avez des tests mal construits. Seul test de boîte arrière avec ces tests unitaires. Votre professeur a raison: ça peut être l'un ou l'autre. Mais seulement si mal fait.

David Arno
la source
1

J'étais en train d'écrire des tests unitaires qui effectuent des tests en boîte noire. Autrement dit, je teste les méthodes publiques dans une classe et par implication de la logique de test des résultats dans les méthodes privées qu'elles appellent.

Je le fais en changeant les entrées de la méthode publique en cours de test unitaire et en testant les sorties attendues qui sont déterminées ou modifiées par la logique dans les méthodes privées de support, dont la mise en œuvre, mes "tests unitaires" n'ont besoin de rien savoir.

Donc, rien ne vous empêche d'effectuer des tests de boîte noire sur les tests unitaires et les tests se briseront si quelqu'un gâche l'implémentation de la logique de support cachée. En fait, cela semble être une approche supérieure et plus efficace qu'une unité de boîte blanche testant tout dans une classe pour le plaisir. Je suis avec le professeur.

Shooresh
la source