Les réponses existantes sont certes bonnes, mais je n'ai vu personne aborder cette idée fausse fondamentale dans la question:
à tout moment, tous les tests unitaires doivent réussir
Non, ce ne sera certainement pas vrai. Pendant que je développe un logiciel, NCrunch est le plus souvent brun (échec de la construction) ou rouge (test ayant échoué).
NCrunch doit être vert (tous les tests réussis ), c'est quand je suis prêt à envoyer un commit au serveur de contrôle de code source, car à ce moment-là, d'autres personnes peuvent créer une dépendance à mon code.
Cela alimente également le sujet de la création de nouveaux tests: les tests doivent affirmer la logique et le comportement du code. Conditions aux limites, conditions de défaut, etc. Lorsque j'écris de nouveaux tests, j'essaie d'identifier ces "points chauds" dans le code.
Les tests unitaires expliquent comment mon code doit être appelé - conditions préalables, résultats attendus, etc.
Si un test est interrompu suite à une modification, je dois décider si le code ou le test est erroné.
En passant, les tests unitaires vont parfois de pair avec le développement piloté par les tests. L'un des principes de la TDD est que les tests cassés sont vos points de repère. Lorsqu'un test échoue, vous devez corriger le code pour que le test réussisse. Voici un exemple concret du début de cette semaine:
Contexte : J'ai écrit et supporte maintenant une bibliothèque utilisée par nos développeurs pour valider les requêtes Oracle. Nous avions des tests qui affirmaient que la requête correspondait à une valeur attendue, ce qui rendait la casse importante (ce n'était pas Oracle) et approuvait joyeusement les requêtes non valides tant qu'elles correspondaient complètement à la valeur attendue.
Au lieu de cela, ma bibliothèque analyse la requête à l'aide de la syntaxe Antlr et Oracle 12c, puis encapsule diverses assertions sur l'arbre de syntaxe lui-même. Des choses comme, c'est valide (aucune erreur d'analyse n'a été générée), tous ses paramètres sont satisfaits par la collection de paramètres, toutes les colonnes attendues lues par le lecteur de données sont présentes dans la requête, etc. Tous ces éléments ont été glissés jusqu'à production à différents moments.
Un de mes collègues ingénieurs m'a envoyé lundi une question qui avait échoué (ou plutôt, qui avait réussi alors qu'il aurait dû échouer) au cours du week-end. Ma bibliothèque a dit que la syntaxe était correcte, mais elle a explosé lorsque le serveur a essayé de l'exécuter. Et quand il a regardé la requête, il était évident pourquoi:
UPDATE my_table(
SET column_1 = 'MyValue'
WHERE id_column = 123;
J'ai chargé le projet et ajouté un test unitaire affirmant que cette requête ne devait pas être valide. De toute évidence, le test a échoué.
Ensuite, je débogués le test défaillant, par le code entrai où je m'y attendais à jeter l'exception, et compris que Antlr a soulevé une erreur sur les paren ouvertes, mais pas en quelque sorte le code précédent attendait. J'ai modifié le code, vérifié que le test était maintenant vert (réussi) et qu'aucun autre utilisateur n'avait été interrompu, engagé et poussé.
Cela a pris peut-être 20 minutes et, au cours du processus, j’ai considérablement amélioré la bibliothèque car elle supportait désormais toute une gamme d’erreurs qu’elle ignorait auparavant. Si je n'avais pas de tests unitaires pour la bibliothèque, la recherche et la résolution du problème auraient pu prendre des heures.