Au cours des dernières semaines, j'ai réfléchi et recherché comment combler une lacune dans notre méthodologie de test. En termes simplifiés, les tests unitaires sont trop petits et les tests d'intégration traditionnels sont trop grands.
Un scénario fréquent se présente où A
et les B
deux utilisent le composant C
. Cependant A
et B
ont des exigences légèrement différentes pour, et font des hypothèses légèrement différentes sur C
. Si je suis le développeur de A
comment et où dois-je tester mes hypothèses C
?
De toute évidence, les tests unitaires A
avec des hypothèses simulées C
sont corrects pour les tests A
de manière isolée, mais ils ne testent pas les hypothèses elles-mêmes.
Une autre possibilité consiste à ajouter des tests unitaires pour C
. Cependant, ce n'est pas idéal car, A
en cours de développement, la modification des tests C
avec des hypothèses évolutives A
sera excessivement maladroite. En effet, A
le développeur peut ne pas même avoir un accès adéquat aux tests unitaires de C
(par exemple une bibliothèque externe).
Pour encadrer cela avec un exemple plus concret: Supposons qu'il s'agit d'une application de nœud. A
, et B
dépendent C
de la lecture d'un fichier (entre autres) et du stockage du contenu du fichier dans l'objet transmis à C
. Au début, tous les fichiers qui C
sont gérés sont petits et peuvent être lus de manière synchrone sans blocage significatif. Cependant, le développeur de se B
rend compte que ses fichiers deviennent énormes et doit passer C
à une lecture asynchrone. Il en résulte un bogue de synchronisation sporadique A
, qui suppose toujours la C
lecture des fichiers de manière synchrone.
Il s'agit du type de bogue qui est notoirement difficile à détecter à partir des tests d'intégration complets et qui peut ne pas être détecté du tout dans les tests d'intégration. Il n'est pas non plus pris en compte par A
les tests unitaires car les A
hypothèses sont faussées. Cependant, il pourrait facilement être rattrapé par un "mini" test d'intégration qui s'exerce simplement A
et C
.
Je n'ai trouvé que quelques références à ce type de test. Intégration dans les petites , tests d' intégration des composants , Unité de l' intégration de test. Il se rapporte également quelque peu à la direction des tests BDD plutôt qu'aux tests unitaires TDD formels.
Comment puis-je combler cette lacune de test? Plus précisément - où dois-je mettre ces tests? Comment se moquer des entrées de A
et C
pour les "mini" tests d'intégration? Et combien d'efforts devraient être déployés pour séparer les problèmes de test entre ces tests et les tests unitaires? Ou existe-t-il une meilleure façon de combler l'écart de test?
Réponses:
Il me semble que vous avez un problème fondamental avec vos composants.
C devrait faire ce que C doit faire et être testé, documenté et conçu pour faire exactement cela. Lorsque vous avez une situation où C est conçu pour «faire ce que B veut», vous avez une relation abusive, qui devient très claire lorsque A arrive et veut que C fasse quelque chose de légèrement différent.
Ce que vous ne devriez pas faire, c'est tester les unités C dans le contexte de A, et surtout pas A dans le contexte de C - vous testez A indépendamment, et vous fournissez les résultats d'un C simulé à A. Si la version réelle de C ne fournit pas ces mêmes résultats, alors vous avez un bug ou un défaut de conception dans C qui sera détecté lorsque vous effectuerez vos gros tests d'intégration. Les tests unitaires ont toujours été de cette façon - vous ne pouvez pas tester une unité en testant une autre unité en même temps. Les tests unitaires ne sont tout simplement pas conçus pour cela.
Les tests d'intégration ne doivent pas nécessairement être "l'ensemble du programme", bien qu'ils soient souvent configurés de cette façon. Ils peuvent être un banc d'essai qui exécute A et C ensemble sans exécuter le reste du programme (ou aussi peu que possible). À ce stade, je ne peux pas vous conseiller davantage car cela dépend de ce que font ces composants et de la façon dont ils interagissent avec le reste de votre programme, mais il est généralement possible d'écrire un banc de test qui fournit une couverture de test des deux composants. Que cela vaille la peine de le faire ou qu'il soit plus efficace de tester l'intégralité du programme en un seul (même si vous exécutez un sous-ensemble des tests d'intégration) est une question à laquelle vous seul pouvez répondre. La plupart des tests d'intégration sont composés de nombreuses sections, donc j'espère que vous devriez être en mesure d'exécuter uniquement celles pertinentes pour ces 2 composants (et sinon,
la source