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;
}
DoSomething
est 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 DoSomething
vous, 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 Log
est 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, DoSomething
le 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 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.
Maintenant, comparez les deux scénarios.
Le même bug cassera un seul test unitaire.
- Toutes vos fonctionnalités utilisant le cassé
Log
sont rouges
- Tous vos tests unitaires sont verts, seul le test unitaire
Log
est 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 .
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.
la source
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 ^ _ ^
la source
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
Sentence
classe, si elle utilise laWord
classe, alors votreWord
classe devrait être moquée. De cette façon, vous ne testerez que lesSentence
fonctionnalités de votre classe.la source
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.
la source
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.
la source
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:
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.
la source
Dans le test unitaire, vous testez chaque partie isolée:
dans le test d'intégration, vous testez de nombreux modules de votre système:
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):
Sources: source1 source2
la source
À 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.
la source
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.
la source
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).
la source
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é.
la source
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.
la source
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.
la source
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 .
la source
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:
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.
la source
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.
la source
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.
la source
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.Assume
classe pour tester la disponibilité des éléments d'environnement (par exemple, la connexion à la base de données) ou d'autres conditions.la source
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é!
la source