Quelle est la différence entre l'intégration et les tests unitaires?

307

Je connais la soi-disant définition de manuels des tests unitaires et des tests d'intégration. Ce qui m'intéresse, c'est quand il est temps d'écrire des tests unitaires ... Je vais les écrire pour couvrir autant d'ensembles de classes que possible.

Par exemple, si j'ai une Wordclasse, j'écrirai des tests unitaires pour la Wordclasse. Ensuite, je commence à écrire ma Sentenceclasse, et quand elle doit interagir avec la Wordclasse, j'écrirai souvent mes tests unitaires de telle sorte qu'ils testent les deux Sentenceet Word... au moins aux endroits où ils interagissent.

Ces tests sont-ils devenus essentiellement des tests d'intégration parce qu'ils testent maintenant l'intégration de ces 2 classes, ou s'agit-il simplement d'un test unitaire qui s'étend sur 2 classes?

En général, en raison de cette ligne incertaine, je vais rarement écrire des tests d'intégration ... ou est-ce que j'utilise le produit fini pour voir si toutes les pièces fonctionnent correctement les tests d'intégration réels, même s'ils sont manuels et rarement répétés au-delà de la portée de chaque caractéristique individuelle?

Suis-je en train de mal comprendre les tests d'intégration, ou y a-t-il vraiment très peu de différence entre les tests d'intégration et les tests unitaires?

Mike Stone
la source

Réponses:

300

La principale différence, pour moi, est que les tests d'intégration révèlent si une fonctionnalité fonctionne ou est cassée, car ils stressent le code dans un scénario proche de la réalité. Ils invoquent une ou plusieurs méthodes ou fonctionnalités logicielles et testent s'ils agissent comme prévu.

À l'opposé, un test unitaire testant une seule méthode repose sur l'hypothèse (souvent erronée) que le reste du logiciel fonctionne correctement, car il se moque explicitement de chaque dépendance.

Par conséquent, lorsqu'un test unitaire pour une méthode implémentant une fonctionnalité est vert, cela ne signifie pas que la fonctionnalité fonctionne.

Disons que vous avez une méthode quelque part comme celle-ci:

public SomeResults DoSomething(someInput) {
  var someResult = [Do your job with someInput];
  Log.TrackTheFactYouDidYourJob();
  return someResults;
}

DoSomethingest très important pour votre client: c'est une fonctionnalité, la seule chose qui compte. C'est pourquoi vous écrivez généralement une spécification de concombre en l'affirmant: vous souhaitez vérifier et communiquer que la fonctionnalité fonctionne ou non.

Feature: To be able to do something
  In order to do something
  As someone
  I want the system to do this thing

Scenario: A sample one
  Given this situation
  When I do something
  Then what I get is what I was expecting for

Aucun doute: si le test réussit, vous pouvez affirmer que vous fournissez une fonctionnalité fonctionnelle. C'est ce que vous pouvez appeler la valeur commerciale .

Si vous voulez écrire un test unitaire pour DoSomethingvous, vous devez faire semblant (en utilisant des simulations) que les autres classes et méthodes fonctionnent (c'est-à-dire que toutes les dépendances que la méthode utilise fonctionnent correctement) et affirmer que votre méthode fonctionne.

En pratique, vous faites quelque chose comme:

public SomeResults DoSomething(someInput) {
  var someResult = [Do your job with someInput];
  FakeAlwaysWorkingLog.TrackTheFactYouDidYourJob(); // Using a mock Log
  return someResults;
}

Vous pouvez le faire avec Dependency Injection, ou une méthode d'usine ou n'importe quel Mock Framework ou simplement étendre la classe en cours de test.

Supposons qu'il y ait un bug dans Log.DoSomething() . Heureusement, la spécification Gherkin le trouvera et vos tests de bout en bout échoueront.

La fonctionnalité ne fonctionnera pas, car elle Logest interrompue, pas parce qu'elle [Do your job with someInput]ne fait pas son travail. Et, au fait,[Do your job with someInput] est la seule responsabilité de cette méthode.

Supposons également Log est utilisé dans 100 autres fonctionnalités, dans 100 autres méthodes de 100 autres classes.

Oui, 100 fonctionnalités échoueront. Mais, heureusement, 100 tests de bout en bout échouent également et révèlent le problème. Et oui: ils disent la vérité .

Ce sont des informations très utiles: je sais que j'ai un produit cassé. C'est aussi une information très déroutante: elle ne me dit pas où est le problème. Cela me communique le symptôme, pas la cause profonde.

Pourtant, DoSomethingle test unitaire est vert, car il utilise un faux Log, conçu pour ne jamais se casser. Et, oui: c'est clairement mentir . Il communique qu'une fonctionnalité cassée fonctionne. Comment cela peut-il être utile?

(Si DoSomething()le test unitaire échoue, assurez-vous: [Do your job with someInput]a quelques bugs.)

Supposons que ce soit un système avec une classe cassée: Un système avec une classe cassée

Un seul bogue cassera plusieurs fonctionnalités et plusieurs tests d'intégration échoueront.

Un seul bogue cassera plusieurs fonctionnalités et plusieurs tests d'intégration échoueront

D'un autre côté, le même bug cassera un seul test unitaire.

Le même bug cassera un seul test unitaire

Maintenant, comparez les deux scénarios.

Le même bug cassera un seul test unitaire.

  • Toutes vos fonctionnalités utilisant le cassé Logsont rouges
  • Tous vos tests unitaires sont verts, seul le test unitaire Logest rouge

En fait, les tests unitaires pour tous les modules utilisant une fonctionnalité cassée sont verts car, en utilisant des simulations, ils ont supprimé les dépendances. En d'autres termes, ils évoluent dans un monde idéal, complètement fictif. Et c'est le seul moyen d'isoler les bogues et de les rechercher. Les tests unitaires signifient moquerie. Si vous ne vous moquez pas, vous ne faites pas de tests unitaires.

La différence

Les tests d'intégration indiquent ce qui ne fonctionne pas. Mais ils ne servent à rien de deviner où pourrait être le problème.

Les tests unitaires sont les seuls tests qui vous indiquent où se trouve exactement le bogue. Pour dessiner ces informations, ils doivent exécuter la méthode dans un environnement simulé, où toutes les autres dépendances sont censées fonctionner correctement.

C'est pourquoi je pense que votre phrase "Ou est-ce juste un test unitaire qui s'étend sur 2 classes" est en quelque sorte déplacée. Un test unitaire ne doit jamais couvrir 2 classes.

Cette réponse est essentiellement un résumé de ce que j'ai écrit ici: les tests unitaires mentent, c'est pourquoi je les aime .

Arialdo Martini
la source
6
Une très bonne réponse! Cependant, je veux juste ajouter que la moquerie n'est pas uniquement destinée au test unitaire. Il pourrait également être très utile dans de nombreux cas de test d'intégration.
n.Stenvang
1
Très bonne réponse! Je ne suis tout simplement pas d'accord avec deux points: 1) que les tests d'intégration sont "inutiles pour deviner où le problème pourrait être"; et 2) "un test unitaire ne devrait jamais couvrir 2 classes". J'ai créé de nombreux tests d'intégration, et lorsqu'ils se cassent, il n'est généralement pas difficile de localiser la source du problème, à condition d'obtenir une trace complète de la pile ou une seule assertion ayant échoué (auquel cas il peut être plus difficile de trouver la source, mais pas tant, car le test d'intégration fournit un contexte contenu pour le débogage). (suite)
Rogério
5
Les tests unitaires peuvent exercer plusieurs classes, à condition qu'il ne s'agisse pas de classes publiques qui devraient avoir leurs propres tests unitaires distincts. Un cas se présente lorsqu'une classe publique testée utilise d'autres classes auxiliaires non publiques qui n'existent que pour prendre en charge la classe publique; dans ce cas, l '"unité" comprend deux classes ou plus. Un autre cas est que la plupart des classes utilisent des classes tierces (la classe String / string, les classes de collection, etc.) qui n'ont pas de sens pour être moquées ou isolées; nous les considérons simplement comme des dépendances stables et fiables qui sont en dehors de la portée des tests.
Rogério
2
Avec les tests d'intégration, il est un peu plus difficile de trouver le problème racine, mais vous pouvez toujours le déboguer et trouver le problème racine. En supposant que les tests unitaires n'échouent pas souvent, il faudra peut-être rarement un peu plus de temps pour corriger les bogues si vous n'avez que des tests d'intégration, mais vous obtenez également la valeur ajoutée de tester l'intégration des composants et vous économisez du temps d'écriture les tests unitaires. Je pense que cette affirmation (qui vient de mon patron) est fausse, mais je ne sais pas comment puis-je le convaincre, des idées?
BornToCode
1
Par le raisonnement de cette réponse, on pourrait soutenir qu'il pourrait être plus efficace de passer du temps à écrire des tests unitaires et de gagner du temps en localisant la source des tests d'intégration ayant échoué lorsqu'ils échouent.
62

Lorsque j'écris des tests unitaires, je limite la portée du code testé à la classe que j'écris actuellement en se moquant des dépendances. Si j'écris une classe de phrase et que la phrase dépend de Word, j'utiliserai un faux mot. En se moquant de Word, je ne peux me concentrer que sur son interface et tester les différents comportements de ma classe Phrase lorsqu'elle interagit avec l'interface de Word. De cette façon, je teste uniquement le comportement et l'implémentation de Sentence et non en même temps, je teste l'implémentation de Word.

Une fois que j'ai écrit les tests unitaires pour garantir que Phrase se comporte correctement lorsqu'elle interagit avec Word en fonction de l'interface de Word, j'écris le test d'intégration pour m'assurer que mes hypothèses sur les interactions étaient correctes. Pour cela, je fournis les objets réels et j'écris un test qui exerce une fonctionnalité qui finira par utiliser à la fois la phrase et le mot.

Larry Foulkrod
la source
43

Mes 10 bits: D

On m'a toujours dit que les tests unitaires sont les tests d'un composant individuel - qui doivent être exercés au maximum. Maintenant, cela a tendance à avoir plusieurs niveaux, car la plupart des composants sont constitués de petites pièces. Pour moi, une unité est une partie fonctionnelle du système. Il doit donc fournir quelque chose de valeur (c'est-à-dire pas une méthode d'analyse de chaîne, mais un HtmlSanitizer peut-être).

Tests d'intégration est l'étape suivante vous, prendre un ou plusieurs composants et faire en sorte qu'ils travaillent ensemble comme ils le devraient .. Vous êtes alors au- dessus des subtilités de l' inquiétude au sujet de la façon dont les composants fonctionnent individuellement, mais lorsque vous entrez html dans votre HtmlEditControl , il en quelque sorte comme par magie sait si son valide ou non ..

C'est une vraie ligne mobile cependant .. Je préfère me concentrer davantage sur le fonctionnement du fichu code à l'arrêt complet ^ _ ^

Rob Cooper
la source
23

Les tests unitaires utilisent des simulacres

Ce dont vous parlez, ce sont des tests d'intégration qui testent en fait toute l'intégration de votre système. Mais lorsque vous effectuez des tests unitaires, vous devez réellement tester chaque unité séparément. Tout le reste devrait être moqué. Donc, dans votre cas de Sentenceclasse, si elle utilise la Wordclasse, alors votre Wordclasse devrait être moquée. De cette façon, vous ne testerez que les Sentencefonctionnalités de votre classe.

Robert Koritnik
la source
Je sais que c'est un ancien poste mais je viens de le découvrir. Et si vous aviez une troisième classe appelée Police avec laquelle la classe Phrase interagit et que vous souhaitez tester la fonctionnalité entre Word et la classe Phrase, vous avez dû vous moquer de la classe Font, mais cela ne fera pas d'elle un test unitaire. Donc, ce que je dis, c'est que l'utilisation de mocks n'en fait pas nécessairement un test unitaire, les mocks peuvent également être utilisés dans les tests d'intégration.
n.Stenvang
2
Bien entendu, les simulations peuvent être utilisées dans les tests d'intégration, mais pour qu'un test unitaire soit réellement en tant que tel, tout ce qui est externe à l' unité doit être simulé . Si les tests d'intégration utilisent des simulations, il s'agit probablement de tests d'intégration partiels (si ce terme existe). Il existe bien sûr des tests d'intégration partiels qui sont descendants ou ascendants. Ces derniers ne nécessitent généralement pas de moqueries, contrairement aux anciens.
Robert Koritnik
17

Je pense que lorsque vous commencez à penser aux tests d'intégration, vous parlez plus d'un croisement entre des couches physiques plutôt que des couches logiques.

Par exemple, si vos tests se préoccupent de générer du contenu, c'est un test unitaire: si votre test ne concerne que l'écriture sur le disque, c'est toujours un test unitaire, mais une fois que vous testez à la fois les E / S ET le contenu du fichier, alors vous avez vous-même un test d'intégration. Lorsque vous testez la sortie d'une fonction dans un service, c'est un test unitaire, mais une fois que vous effectuez un appel de service et voyez si le résultat de la fonction est le même, c'est un test d'intégration.

Techniquement, vous ne pouvez de toute façon pas tester unitaire une seule classe. Et si votre classe est composée de plusieurs autres classes? Cela en fait-il automatiquement un test d'intégration? Je ne pense pas.

Jon Limjap
la source
8
"Techniquement, vous ne pouvez pas tester les unités d'une seule classe de toute façon. Et si votre classe est composée de plusieurs autres classes?" Eh bien, un test unitaire "strict" ne ferait que simuler / écraser toutes les dépendances. Cependant, il est discutable que ce soit toujours pratique ...
sleske
2
C'est vrai sieske - l'important est de pouvoir garder les dépendances au minimum absolu.
Jon Limjap
-1, un test unitaire ne teste pas une seule fonctionnalité, mais une seule fonction ou classe logicielle, c'est-à-dire qu'il teste une unité logique de logiciel.
CharlesB
12

en utilisant la conception à responsabilité unique, son noir et blanc. Plus d'une responsabilité, c'est un test d'intégration.

Par le test du canard (regards, charlatans, daims, c'est un canard), c'est juste un test unitaire avec plus de 1 nouvel objet.

Lorsque vous entrez dans mvc et le testez, les tests du contrôleur sont toujours l'intégration, car le contrôleur contient à la fois une unité de modèle et une unité de vue. En testant la logique dans ce modèle, j'appellerais un test unitaire.

DevelopingChris
la source
10

La nature de vos tests

Un test unitaire du module X est un test qui s'attend (et recherche) des problèmes uniquement dans le module X.

Un test d'intégration de nombreux modules est un test qui s'attend à des problèmes qui découlent de la coopération entre les modules, de sorte que ces problèmes seraient difficiles à trouver en utilisant des tests unitaires seuls.

Pensez à la nature de vos tests dans les termes suivants:

  • Réduction des risques : c'est à cela que servent les tests. Seule une combinaison de tests unitaires et de tests d'intégration peut vous offrir une réduction complète des risques, car d'une part, les tests unitaires ne peuvent intrinsèquement pas tester l'interaction appropriée entre les modules et, d'autre part, les tests d'intégration peuvent exercer la fonctionnalité d'un module non trivial uniquement dans une faible mesure.
  • Effort d'écriture de test : les tests d'intégration peuvent économiser de l'effort car vous n'aurez alors pas besoin d'écrire des stubs / fakes / mocks. Mais les tests unitaires peuvent également économiser des efforts, lors de la mise en œuvre (et de la maintenance!) De ces stubs / fakes / mocks qui s'avèrent plus faciles que de configurer la configuration de test sans eux.
  • Délai d'exécution des tests : les tests d'intégration impliquant des opérations lourdes (telles que l'accès à des systèmes externes tels que des bases de données ou des serveurs distants) ont tendance à être plus lent (euh). Cela signifie que les tests unitaires peuvent être exécutés beaucoup plus fréquemment, ce qui réduit les efforts de débogage en cas d'échec, car vous avez une meilleure idée de ce que vous avez modifié entre-temps. Cela devient particulièrement important si vous utilisez le développement piloté par les tests (TDD).
  • Effort de débogage : si un test d'intégration échoue, mais qu'aucun des tests unitaires ne le fait, cela peut être très gênant, car il y a tellement de code impliqué qui peut contenir le problème. Ce n'est pas un gros problème si vous n'avez précédemment modifié que quelques lignes - mais comme les tests d'intégration s'exécutent lentement, vous ne les avez peut-être pas exécutés à des intervalles aussi courts ...

Rappelez-vous qu'un test d'intégration peut toujours bloquer / simuler / simuler certaines de ses dépendances. Cela fournit un bon compromis entre les tests unitaires et les tests système (les tests d'intégration les plus complets, testant l'ensemble du système).

Approche pragmatique de l'utilisation des deux

Une approche pragmatique serait donc la suivante: s'appuyer de manière flexible sur les tests d'intégration autant que possible et utiliser des tests unitaires lorsque cela serait trop risqué ou gênant. Cette manière de penser peut être plus utile que certaines discriminations dogmatiques des tests unitaires et des tests d'intégration.

Lutz Prechelt
la source
10

Dans le test unitaire, vous testez chaque partie isolée: entrez la description de l'image ici

dans le test d'intégration, vous testez de nombreux modules de votre système:

entrez la description de l'image ici

et c'est ce qui se produit lorsque vous n'utilisez que des tests unitaires (généralement les deux fenêtres fonctionnent, malheureusement pas ensemble):

entrez la description de l'image ici

Sources: source1 source2

Michu93
la source
Vous avez trois images mais seulement deux sources.
gerrit
1
@gerrit jetez un œil à la première source - deux photos sont de là
Michu93
1
Aimez cette réponse 👏
Dzenis H.
8

À mon avis, la réponse est "Pourquoi est-ce important?"

Est-ce parce que les tests unitaires sont quelque chose que vous faites et les tests d'intégration que vous ne faites pas? Ou vice versa? Bien sûr que non, vous devriez essayer de faire les deux.

Est-ce parce que les tests unitaires doivent être rapides, isolés, répétables, auto-validés et opportuns et que les tests d'intégration ne le devraient pas? Bien sûr que non, tous les tests devraient être ceux-ci.

C'est parce que vous utilisez des maquettes dans les tests unitaires mais que vous ne les utilisez pas dans les tests d'intégration? Bien sûr que non. Cela impliquerait que si j'ai un test d'intégration utile, je ne suis pas autorisé à ajouter une maquette pour une partie, craignez de devoir renommer mon test en "test unitaire" ou de le remettre à un autre programmeur pour y travailler.

Est-ce parce que les tests unitaires testent une unité et les tests d'intégration testent un certain nombre d'unités? Bien sûr que non. De quelle importance pratique est-ce? La discussion théorique sur la portée des tests échoue de toute façon dans la pratique parce que le terme "unité" dépend entièrement du contexte. Au niveau de la classe, une unité peut être une méthode. Au niveau de l'assemblage, une unité peut être une classe et au niveau du service, une unité peut être un composant. Et même les classes utilisent d'autres classes, alors quelle est l'unité?

Cela n'a aucune importance.

Les tests sont importants, FIRST est important, séparer les cheveux des définitions est une perte de temps qui ne fait que confondre les nouveaux arrivants avec les tests.

David Sackstein
la source
5
-1 La définition est ce qui rend les gens capables d'utiliser les mêmes termes sans toujours expliquer ce qu'ils signifient, et est essentielle à la collaboration. En tant que tel, il est essentiel de comprendre la différence entre les deux notions.
CharlesB
Comme @CharlesB l'a mentionné, il est important de ne pas avoir besoin d'expliquer à chaque fois ou de trouver que tout le monde a une définition différente, ce qui crée de la confusion. Les tests seront écrits différemment et exécutés différemment, mais cela ne signifie pas que les deux ne doivent pas être effectués en voulant définir les différences.
Shane
La conclusion de la réponse peut être extrême, mais la plupart de ses points sont tout à fait valables: les tests unitaires et les tests d'intégration sont généralement la même chose, sauf pour leur granularité - et il n'est pas évident où une ligne doit être tracée entre eux.
Lutz Prechelt
Cela n'aide pas lors de la création d'un langage commun dans un environnement professionnel. Alors que la plupart du temps, vous avez raison, peu importe, ne pas avoir un langage commun créera des malentendus et de la confusion au sein de l'équipe. Je pense que la meilleure option est de faire en sorte que l'équipe se mette d'accord sur leurs termes et définitions.
user924272
4

Je pense que j'appellerais encore quelques classes interactives un test unitaire à condition que les tests unitaires pour la classe 1 testent les fonctionnalités de la classe 1, et les tests unitaires pour la classe 2 testent ses fonctionnalités, et aussi qu'ils ne frappent pas la base de données.

J'appelle un test un test d'intégration lorsqu'il traverse la majeure partie de ma pile et atteint même la base de données.

J'aime vraiment cette question, car la discussion TDD me semble parfois un peu trop puriste, et c'est bon pour moi de voir des exemples concrets.

Lance Fisher
la source
4

Je fais de même - je les appelle tous les tests unitaires, mais à un moment donné, j'ai un "test unitaire" qui couvre tellement de choses que je le renomme souvent en "..IntegrationTest" - juste un changement de nom seulement, rien d'autre ne change.

Je pense qu'il y a une suite de "tests atomiques" (test d'une petite classe ou d'une méthode) aux tests unitaires (niveau classe) et aux tests d'intégration - puis au test fonctionnel (qui couvre normalement beaucoup plus de choses de haut en bas) - il ne semble pas y avoir de coupure nette.

Si votre test configure des données et charge peut-être une base de données / un fichier, etc., il s'agit peut-être plutôt d'un test d'intégration (les tests d'intégration que je trouve utilisent moins de simulations et plus de classes réelles, mais cela ne signifie pas que vous ne pouvez pas simuler certaines du système).

Michael Neale
la source
4

Le test unitaire est une méthode de test qui vérifie que les unités individuelles de code source fonctionnent correctement.

Test d'intégration est la phase de test logiciel dans laquelle les modules logiciels individuels sont combinés et testés en tant que groupe.

Wikipedia définit une unité comme la plus petite partie testable d'une application, qui en Java / C # est une méthode. Mais dans votre exemple de la Parole et la classe de phrase que je serais probablement juste les tests à peine que je trouverais probablement il Overkill d'utiliser une fausse classe de mots afin de tester la classe de phrase. Donc la phrase serait mon unité et le mot est un détail d'implémentation de cette unité.

grom
la source
4

Tests d'intégration: la persistance de la base de données est testée.
Tests unitaires: l'accès à la base de données est simulé. Les méthodes de code sont testées.

Pascal
la source
3

Le test unitaire consiste à tester une unité de travail ou un bloc de code si vous le souhaitez. Habituellement réalisé par un seul développeur.

Les tests d'intégration font référence au test effectué, de préférence sur un serveur d'intégration, lorsqu'un développeur valide son code dans un référentiel de contrôle de source. Les tests d'intégration peuvent être effectués par des utilitaires tels que Cruise Control.

Vous effectuez donc vos tests unitaires pour vérifier que l'unité de travail que vous avez créée fonctionne, puis le test d'intégration valide que tout ce que vous avez ajouté au référentiel n'a pas cassé autre chose.

Christian Hagelid
la source
2

J'appelle les tests unitaires ces tests que la boîte blanche teste une classe. Toutes les dépendances dont la classe a besoin sont remplacées par de fausses (mocks).

Les tests d'intégration sont les tests où plusieurs classes et leurs interactions sont testées en même temps. Seules certaines dépendances dans ces cas sont truquées / moquées.

Je n'appellerais pas les tests d'intégration de Controller à moins que l'une de leurs dépendances soit réelle (c'est-à-dire non falsifiée) (par exemple IFormsAuthentication).

La séparation des deux types de tests est utile pour tester le système à différents niveaux. De plus, les tests d'intégration ont tendance à durer longtemps et les tests unitaires sont censés être rapides. La distinction de vitesse d'exécution signifie qu'ils sont exécutés différemment. Dans nos processus de développement, les tests unitaires sont exécutés lors de l'enregistrement (ce qui est bien car ils sont super rapides) et les tests d'intégration sont exécutés une / deux fois par jour. J'essaie et exécute des tests d'intégration aussi souvent que possible, mais généralement je frappe la base de données / écrit dans des fichiers / rend les rpc / etc ralentis.

Cela soulève un autre point important, les tests unitaires devraient éviter de toucher IO (par exemple, disque, réseau, db). Sinon, ils ralentissent beaucoup. Il faut un peu d'effort pour concevoir ces dépendances d'E / S - je ne peux pas admettre que j'ai été fidèle à la règle "les tests unitaires doivent être rapides", mais si vous l'êtes, les avantages sur un système beaucoup plus grand deviennent très rapidement apparents .

CVertex
la source
2

Explication simple avec des analogies

Les exemples ci-dessus fonctionnent très bien et je n'ai pas besoin de les répéter. Je vais donc me concentrer sur l'utilisation d'exemples pour vous aider à comprendre.

Tests d'intégration

Les tests d'intégration vérifient si tout fonctionne correctement. Imaginez une série de rouages ​​travaillant ensemble dans une montre. Un test d'intégration serait: la montre indique-t-elle l'heure exacte? Dit-il toujours l'heure exacte dans 3 jours?

Tout ce qu'il vous dit, c'est si la pièce dans son ensemble fonctionne. S'il échoue: il ne vous dit pas exactement où il échoue.

Tests unitaires

Ce sont des types de tests vraiment spécifiques. Ils vous indiquent si une chose spécifique fonctionne ou échoue. La clé de ce type de test est qu'il ne teste qu'une chose spécifique tout en supposant que tout le reste fonctionne très bien. Voilà le point clé.

Exemple: Développons ce point à l'aide d'un exemple:

  • Prenons l'exemple d'une voiture.
  • L'intégrationTest d' pour une voiture: par exemple, la voiture se rend-elle à Woop Woop et vice-versa? Si c'est le cas, vous pouvez dire en toute sécurité qu'une voiture fonctionne d'un point de vue global. Il s'agit d'un test d'intégration. Si elle échoue, vous ne savez pas où elle est réellement en panne: est-ce le radiateur, la transmission, le moteur ou le carburateur? Tu n'as aucune idée. Ça pourrait être n'importe quoi.
  • Test unitaire pour une voiture: le moteur fonctionne-t-il? Ce test suppose que tout le reste de la voiture fonctionne très bien. De cette façon, si ce test unitaire particulier échoue: vous pouvez être très sûr que le problème réside dans le moteur - vous pouvez donc rapidement isoler et résoudre le problème.

Utilisation de talons

  • Supposons que votre test d'intégration de voiture échoue. Il ne conduit pas avec succès à Echuca. Où est le problème?

  • Supposons maintenant que votre moteur utilise un système d'injection de carburant spécial et que ce test d'unité moteur ait également échoué. En d'autres termes, le test d'intégration et le test de l'unité moteur ont échoué. Où est donc le problème? (Donnez-vous 10 secondes pour obtenir la réponse.)

  • Le problème vient-il du moteur ou du système d'injection de carburant?

Vous voyez le problème ici? Vous ne savez pas exactement ce qui échoue. Si vous utilisez différentes dépendances externes, chacune de ces 10 pourrait avoir causé le problème - et vous ne saurez pas par où commencer. C'est pourquoi les tests unitaires utilisent des talons pour supposer que tout le reste fonctionne très bien.

BKSpurgeon
la source
1

Un peu académique cette question, n'est-ce pas? ;-) Mon point de vue: Pour moi, un test d'intégration est le test de toute la partie, pas si deux parties sur dix vont ensemble. Notre test d'intégration montre si le build principal (contenant 40 projets) réussira. Pour les projets, nous avons des tonnes de tests unitaires. La chose la plus importante concernant les tests unitaires pour moi est qu'un test unitaire ne doit pas dépendre d'un autre test unitaire. Donc, pour moi, les deux tests que vous décrivez ci-dessus sont des tests unitaires, s'ils sont indépendants. Pour les tests d'intégration, cela n'a pas besoin d'être important.

John Smithers
la source
1

Ces tests sont-ils devenus essentiellement des tests d'intégration car ils testent désormais l'intégration de ces 2 classes? Ou s'agit-il simplement d'un test unitaire qui s'étend sur 2 classes?

Je pense que oui et oui. Votre test unitaire qui s'étend sur 2 classes est devenu un test d'intégration.

Vous pouvez l'éviter en testant la classe Phrase avec une implémentation fictive - la classe MockWord, qui est importante lorsque ces parties du système sont suffisamment grandes pour être implémentées par différents développeurs. Dans ce cas, Word est testé unitaire seul, Phrase est testé unitaire avec l'aide de MockWord, puis Phrase est testé en intégration avec Word.

Un exemple de différence réelle peut être suivi 1) Un réseau de 1 000 000 d'éléments est facilement testé à l'unité et fonctionne correctement. 2) BubbleSort est facilement testé à l'unité sur une maquette de 10 éléments et fonctionne également très bien 3) Les tests d'intégration montrent que quelque chose ne va pas si bien.

Si ces parties sont développées par une seule personne, le problème le plus probable sera trouvé lors du test unitaire de BubbleSoft simplement parce que le développeur a déjà un vrai tableau et qu'il n'a pas besoin d'une implémentation simulée.

Pavel Feldman
la source
1

De plus, il est important de se rappeler que les tests unitaires et les tests d'intégration peuvent être automatisés et écrits en utilisant, par exemple, JUnit. Dans les tests d'intégration JUnit, on peut utiliser la org.junit.Assumeclasse pour tester la disponibilité des éléments d'environnement (par exemple, la connexion à la base de données) ou d'autres conditions.

Paulo Merson
la source
0

Si vous êtes un puriste TDD, vous écrivez les tests avant d'écrire le code de production. Bien sûr, les tests ne seront pas compilés, vous devez donc d'abord compiler les tests, puis faire passer les tests.

Vous pouvez le faire avec des tests unitaires, mais pas avec des tests d'intégration ou d'acceptation. Si vous avez essayé avec un test d'intégration, rien ne se compilerait tant que vous n'auriez pas terminé!

StevePoling
la source