Tests unitaires automatisés, tests d'intégration ou tests d'acceptation [clôturé]


29

Le TDD et les tests unitaires semblent être la grande rave en ce moment. Mais est-ce vraiment utile par rapport à d'autres formes de tests automatisés?

Intuitivement, je suppose que les tests d'intégration automatisés sont bien plus utiles que les tests unitaires. D'après mon expérience, le plus de bugs semble être dans l'interaction entre les modules, et pas tellement la logique réelle (généralement limitée) de chaque unité. De plus, des régressions se sont souvent produites en raison de la modification des interfaces entre les modules (et des conditions préalables et postérieures modifiées.)

Suis-je en train de mal comprendre quelque chose, ou pourquoi les tests unitaires se concentrent-ils autant que les tests d'intégration? C'est simplement parce que l'on suppose que les tests d'intégration sont quelque chose que vous avez, et que les tests unitaires sont la prochaine chose que nous devons apprendre à appliquer en tant que développeurs?

Ou peut-être que les tests unitaires donnent simplement le gain le plus élevé par rapport à la complexité de l'automatisation?

Quelle est votre expérience avec les tests unitaires automatisés, les tests d'intégration automatisés et les tests d'acceptation automatisés, et d'après votre expérience, qu'est-ce qui a produit le ROI le plus élevé? et pourquoi?

Si vous deviez choisir une seule forme de test pour être automatisé sur votre prochain projet, lequel serait-ce?

Merci d'avance.


Je voudrais juste ajouter un lien tardif vers les tests d'intégration de JB Rainsberger sont une arnaque . Il met en évidence de nombreuses raisons pour lesquelles les tests d'intégration sont une fausse économie.
Tim


6
Voilà encore un autre exemple de fermeture d'une question qui allait parfaitement bien sur ce site lorsqu'elle a été posée il y a trois ans! C'est vraiment ennuyeux de contribuer à une communauté où les règles changent et où vous jetez simplement tous les vieux trucs!
Bjarke Freund-Hansen

Réponses:


34

La rétroaction rapide est un facteur important qui rend les tests unitaires extrêmement utiles .

Considérez ce qui se passe lorsque votre application est entièrement couverte de tests d'intégration / système / fonctionnels (ce qui est déjà une situation idéale, loin de la réalité dans la plupart des magasins de développement). Ils sont souvent gérés par une équipe de test dédiée.

  • Vous validez une modification du référentiel SCM,
  • parfois (peut-être quelques jours) plus tard, les testeurs obtiennent une nouvelle version interne et commencent à la tester,
  • ils trouvent un bug et déposent un rapport de bug,
  • (dans le cas idéal), quelqu'un vous attribue le rapport de bogue.

Tout cela peut prendre des jours, voire des semaines. À ce moment-là, vous avez déjà travaillé sur d'autres tâches, vous n'avez donc pas les moindres détails du code écrits plus tôt dans votre esprit. De plus, vous n'avez généralement même aucune preuve directe de l'emplacement réel du bogue, il faut donc beaucoup de temps pour trouver et corriger le bogue.

Alors que dans les tests unitaires (TDD)

  • vous écrivez un test,
  • vous écrivez du code pour satisfaire le test,
  • le test échoue toujours,
  • vous regardez le code et vous avez généralement une expérience "oups" en quelques secondes (comme "oups, j'ai oublié de vérifier cette condition!"), puis
  • corrige le bogue immédiatement.

Tout cela se produit en quelques minutes .

Cela ne veut pas dire que les tests d'intégration / système ne sont pas utiles; ils servent simplement à des fins différentes. Avec des tests unitaires bien écrits, vous pouvez détecter une grande partie des bogues dans le code avant qu'ils n'atteignent la phase d'intégration, où il est déjà beaucoup plus cher de les trouver et de les corriger. Vous avez raison de dire que les tests d'intégration sont nécessaires pour détecter les types de bogues difficiles ou impossibles à détecter avec les tests unitaires. Cependant, d'après mon expérience, ce sont les types les plus rares; la plupart des bogues que j'ai vus sont causés par une omission simple ou même triviale quelque part dans une méthode.

Sans oublier que les tests unitaires testent également vos interfaces pour la convivialité / sécurité, etc., vous donnant ainsi des commentaires d'une importance vitale pour améliorer votre conception et vos API. Quelle IMHO peut réduire considérablement les risques de bogues d'intégration de modules / sous-systèmes: plus une API est facile et propre, moins il y a de risques de malentendus ou d'omissions.

Quelle est votre expérience avec les tests unitaires automatisés, les tests d'intégration automatisés et les tests d'acceptation automatisés, et d'après votre expérience, qu'est-ce qui a produit le ROI le plus élevé? et pourquoi?

Le retour sur investissement dépend de nombreux facteurs, le plus important étant probablement de savoir si votre projet est entièrement nouveau ou hérité. Avec Greenfield Development, mon conseil (et mon expérience jusqu'à présent) est de faire des tests unitaires de style TDD depuis le début. Je suis convaincu que c'est la méthode la plus rentable dans ce cas.

Dans un projet hérité, cependant, la mise en place d'une couverture suffisante de tests unitaires est une entreprise énorme qui sera très lente à produire des avantages. Il est plus efficace d'essayer de couvrir les fonctionnalités les plus importantes avec des tests système / fonctionnels via l'interface utilisateur si possible. (Les applications GUI de bureau peuvent être difficiles à tester automatiquement via l'interface graphique, bien que les outils de support de test automatisés s'améliorent progressivement ...). Cela vous donne rapidement un filet de sécurité grossier mais efficace. Ensuite, vous pouvez commencer à créer progressivement des tests unitaires autour des parties les plus critiques de l'application.

Si vous deviez choisir une seule forme de test à automatiser sur votre prochain projet, lequel serait-ce?

C'est une question théorique et je la trouve inutile. Toutes sortes de tests ont leur utilité dans la boîte à outils d'un bon ingénieur SW, et tous ont des scénarios où ils sont irremplaçables.


2
+1 pour "rétroaction rapide" pour les tests unitaires. En outre, très pratique pour s'exécuter en tant que post-validation sur un serveur d'intégration continue.
Frank Shearar,

1
"Toutes sortes de tests ont leur utilité dans la boîte à outils d'un bon ingénieur SW, et tous ont des scénarios où ils sont irremplaçables." - J'aimerais pouvoir voter plusieurs fois juste pour ça! Les gens qui pensent pouvoir trouver un outil / méthode de test idéal et l'appliquer partout m'épuisent.
ptyx

8

Tous les types de tests sont très importants et garantissent que les différents aspects du système sont conformes aux spécifications. Donc, pour revenir en arrière, "Si je devais choisir un type de test ..." Je ne le ferais pas. Les tests unitaires me fournissent des commentaires différents des tests d'intégration ou des tests interactifs par une personne.

Voici le type / l'avantage des tests que nous faisons:

  • Test unitaire - garantit que les unités effectuent le travail comme nous nous y attendons. Nous testons les contrats des fournisseurs et des consommateurs pour chaque interface, ce qui est assez facile à automatiser. Nous vérifions également nos conditions aux limites, etc.
  • Test d'intégration - garantit que les unités travaillent ensemble de concert. Il s'agit principalement de tester notre conception. Si quelque chose se casse ici, nous devons ajuster nos tests unitaires pour nous assurer que cela ne se reproduise plus.
  • Test du système - garantit que le système répond aux exigences / spécifications. Habituellement, les gens font ce type de test.
  • Test d'acceptation - le client le fait pour vérifier que le produit final fait ce qui est annoncé.

Tests facultatifs mais recommandés:

  • Test de l'expérience utilisateur: bien que nous recevions des commentaires décents des tests du système, demander aux personnes du client de prévisualiser certaines versions préliminaires peut vraiment aider à déterminer si nous devons changer les choses avant qu'il ne soit trop tard.

Juste pour comprendre pourquoi les tests unitaires ont un avantage sur les tests d'intégration, vous devez comprendre les ordres de grandeur des tests supplémentaires dont vous auriez besoin pour être complets. Pour chaque résultat possible pour l'unité A, il doit y avoir un test. La même chose pour l'unité B. Maintenant, si les deux fonctionnent ensemble pour une solution plus complète, le nombre de tests est combinatoire. En bref, pour tester chaque permutation d'interaction entre l'unité A et l'unité B, vous avez besoin de tests A * B. Ajoutez l'unité C, et le nombre de tests pour le trio serait A * B * C.

C'est là que le concept d'interfaces et de frontières d'objets devient très important. Les interfaces représentent un certain contrat. Un implémenteur d'une interface convient qu'elle se comportera d'une certaine manière. De même, un consommateur d'une interface s'engage à utiliser l'implémentation d'une certaine manière. En écrivant un test qui recueille chaque classe qui implémente une interface, vous pouvez facilement tester que chaque implémentation respecte les contrats d'interface. C'est la moitié de l'équation. L'autre moitié consiste à tester le côté des consommateurs - c'est là que les faux objets entrent en jeu. La maquette est configurée pour garantir que les interactions sont toujours conformes aux spécifications. À ce stade, il suffit de quelques tests d'intégration pour s'assurer que les contrats de mise en œuvre / consommateur sont corrects.


"Test du système - garantit que le système répond aux exigences / spécifications Habituellement, les gens font ce type de test". Les tests d'intégration système / aka fonctionnel / aka "de bout en bout" / aka de haut niveau sont également bons pour l'automatisation.
MiFreidgeim SO-stop étant maléfique

3

Ce sont différents outils avec des objectifs différents:

  • Le test unitaire est un outil de conception (TDD), et presque une condition préalable à la refactorisation.

  • Les tests d'intégration sont excellents pour visualiser la progression du projet, et également excellents pour éviter les bogues de régression.

Le point à retenir est que vous ne pouvez pas vraiment concevoir avec des tests d'intégration, et vous ne trouverez pas de régressions avec des tests unitaires.


@vous ne pouvez pas vraiment concevoir avec des tests d'intégration, et vous ne trouverez pas de régressions avec des tests unitaires. Exactement!
Chankey Pathak

Les tests unitaires peuvent trouver des régressions causées par la refactorisation, par exemple une méthode d'assistance partagée modifiée. Les tests d'intégration sont cependant bien meilleurs pour cela.
StuperUser

Le deuxième point sur les tests d'intégration comprend les tests "système / fonctionnel" (alias "de bout en bout")
MiFreidgeim SO-stop étant mauvais

Entièrement d'accord; Steve Sanderson a fait valoir un point similaire il y a quelques années. Voir le tableau "Objectif - Technique la plus forte" dans son article de blog 2009 sur blog.stevensanderson.com/2009/08/24/… pour des réflexions quelque peu complémentaires aux vôtres ici.
Mark A. Fitzgerald

1

J'ai beaucoup utilisé le sélénium pour les contrôles de santé mentale.

Dans une grande société d'édition Web, lorsqu'une nouvelle version était publiée, il fallait généralement environ 3 testeurs environ une heure ou deux pour visiter toutes les familles de sites et s'assurer que tout allait bien, selon le script de test. Avec Selenium, nous avons pu automatiser les tests et les distribuer sur plusieurs machines et navigateurs. Actuellement, lorsque les scripts de test sont exécutés, il faut à 3 PC environ 10 minutes pour faire automatiquement la même chose ET cracher un joli rapport.

La grande chose à propos du sélénium est que vous pouvez le lier à des cadres de tests unitaires comme XUnit, TestNG ou MSTest.

D'après mon expérience, cela a été extrêmement précieux, mais la configuration de quelque chose comme ça dépend vraiment de votre projet et de votre équipe, donc le retour sur investissement variera certainement.


1

Le meilleur retour sur investissement est généralement le premier test qui peut trouver ce type de bogue.

Les tests unitaires devraient trouver la plupart des bogues qui se trouvent dans une seule méthode, ou peut-être un composant. Il trouve des bogues qui peuvent généralement être corrigés en quelques minutes, avec des délais de traitement totaux inférieurs à une heure. Tests TRÈS bon marché, bogues TRÈS bon marché à trouver et à corriger! Si ces bogues se transforment en tests d'intégration, le délai de traitement peut ressembler davantage à une journée (les tests se produisent souvent tous les soirs), en supposant que le bogue n'est pas occlus par un autre bogue; de plus, il y aura probablement plus de bogues introduits car un autre code a été écrit contre le code de bogue initial; De plus, toute refonte aura un impact sur plus de morceaux de code. De plus, laisser passer plus de bogues signifie avoir à faire beaucoup plus de tests avant de pouvoir terminer les tests d'intégration. Les mauvais tests unitaires sont souvent au cœur de longues, onéreuses et coûteusestester les cycles d'intégration. Ignorer les tests unitaires peut réduire de moitié le temps de développement, mais les tests prendront au moins 3 à 4 fois plus de temps, le projet entier doublera et vous aurez toujours une qualité inférieure à celle d'un IME testé unitaire.

Les tests d'intégration sont généralement les premiers tests réels pouvant détecter des bogues d'intégration (bien que les processus de révision puissent trouver des bogues avant l'écriture du logiciel ou avant que le code ne soit testé). Vous devez trouver ces bogues avant de commencer à montrer le logiciel à l'utilisateur ou à le publier, car la correction des bogues au dernier moment (ou la correction à chaud!) Est très coûteuse. Vous ne pouvez pas trouver ces bogues plus tôt, alors qu'ils seraient moins chers à corriger, car vous avez besoin de plusieurs composants fonctionnels à intégrer (par définition). Les tests d'intégration sont ralentis lorsque des bogues qui n'ont rien à voir avec des éléments interactifs (comme des fautes de frappe mineures) doivent être résolus avant que les tests les plus intéressants puissent même commencer.

Les tests d'acceptation des utilisateurs garantissent que le logiciel fait ce que le client veut (bien que le client soit, espérons-le, impliqué tout le temps, pour réduire le risque de trouver un énorme écart entre les attentes et le logiciel réel à la fin du projet - TRÈS cher !). Au moment où vous arrivez à cette étape des tests, vous devriez vraiment croire que la plupart des bogues de votre produit, au moins par rapport aux spécifications, ont déjà été trouvés. Les tests d'acceptation des utilisateurs consistent davantage à s'assurer que le produit répond aux besoins du client qu'à s'assurer qu'il n'y a pas de bogues par rapport aux spécifications.

Si je devais automatiser un seul type de test, ce serait un test unitaire. Les tests d'intégration peuvent être effectués manuellement et ont été effectués de cette façon par de nombreuses grandes entreprises pendant des années. Il est plus long de faire manuellement un travail qui pourrait être effectué par un ordinateur encore et encore, et beaucoup plus cher pour la plupart des projets, sans parler de l'ennui et des erreurs, mais cela peut être fait. Les tests d'acceptation des utilisateurs sont souvent manuels, car les utilisateurs ne savent souvent pas comment automatiser leurs tests tout en testant ce qui les intéresse. Les tests unitaires DOIVENT être automatisés. Vous devez être en mesure d'exécuter tous les tests unitaires en quelques secondes à la demande aussi souvent que toutes les quelques minutes. Les humains ne peuvent même pas s'approcher des tests manuels. Sans oublier que les tests unitaires sont dans le code, et ne peuvent pas être exécutés sans les appeler via du code, c'est-à-dire les automatiser.

Une chose à garder à l'esprit est qu'il s'agit d'un forum principalement destiné aux développeurs et non aux testeurs. Les tests d'intégration sont principalement mis en œuvre par les testeurs. Les tests unitaires sont mis en œuvre par les développeurs. Naturellement, les développeurs parlent davantage de tests unitaires que d'autres types de tests. Cela ne signifie pas qu'ils ne pensent pas que d'autres tests soient importants. Cela signifie simplement qu'ils ne sont pas réellement faire (ou le faire moins souvent).


Merci surtout pour ce tout dernier paragraphe, je n'y ai pas pensé.
Bjarke Freund-Hansen,

Pour info, j'ai mis à jour la réponse depuis que vous l'avez lue - réalisé que je n'ai pas lu la question d'origine assez attentivement
Ethel Evans

@EthelEvans, vos raisons concernant les priorités des tests unitaires sont correctes pour les nouveaux projets. Pour les projets hérités, qui ont été écrits sans automatiser la couverture des tests, les tests d'intégration système / fonctionnel / aka de haut niveau sont les plus importants. Voir la dernière partie de la réponse programmers.stackexchange.com/a/39370/31574 .
MiFreidgeim SO-stop étant maléfique

@MichaelFreidgeim, cela dépend finalement de la stabilité des interfaces. L'automatisation des tests de haut niveau peut rapidement entraîner des coûts de maintenance prohibitifs s'ils sont obsolètes rapidement. Dans ce cas, automatisez la baisse pour aider à renforcer la stabilité et utilisez des tests exploratoires (éventuellement basés sur une session ou une liste de contrôle) pour les tests E2E et d'intégration pour éviter d'engager des coûts de maintenance d'automatisation désagréables. Cependant, tous les projets hérités n'ont pas d'interfaces stables, en particulier s'ils sont refactorisés ou réorganisés de manière agressive.
Ethel Evans

1

J'ai l'impression que les tests d'acceptation sont roi dans ce scénario.

Si un commit rompt les tests d'acceptation, il doit être trié.

Les tests d'acceptation vous indiquent où se trouve votre logiciel, contrairement aux tests unitaires.

Par conséquent, les tests unitaires peuvent fournir un très faux sentiment de sécurité.


0

La question n'est pas tant ce qui est plus important que ce qui peut être automatisé et exécuté rapidement.

Les tests unitaires montrent si un petit composant est adapté à l'usage d'une manière particulière, et est généralement petit et rapide à exécuter. Étant petits, ils sont généralement assez faciles à automatiser.

Les tests d'intégration montrent si les composants fonctionnent ensemble. Ils sont généralement beaucoup plus gros et peuvent ne pas être faciles à automatiser. Leur exécution peut prendre plus de temps. Il est utile de pouvoir les exécuter automatiquement, mais c'est une tâche plus importante et ils ne seront pas exécutés aussi souvent de toute façon.

Les tests d'acceptation montrent si un projet est acceptable ou non. Il est normalement impossible d'automatiser complètement (bien que les tests automatisés puissent jouer un rôle), car il est normalement impossible de définir les exigences exactes et complètes dans une question formelle qui est moins compliquée que le code source lui-même. Les tests d'acceptation incluent généralement des utilisateurs potentiels qui font des choses avec le système et observent que les résultats sont satisfaisants à tous égards, ce qui est normalement en partie subjectif. Étant donné que les tests d'acceptation sont généralement exécutés une fois (différents clients voudront normalement faire leurs propres tests d'acceptation séparés), cela ne vaut vraiment pas la peine d'être automatisé.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.