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.