N'est-il pas plus simple de passer directement à la troisième étape, et de ne jamais faire de test unitaire de BooksLimit() ?
Oui... Si vous ne passez pas de temps à écrire des tests, vous passerez moins de temps à écrire des tests. Votre projet pourrait prendre plus longtemps globalement, parce que vous passerez beaucoup de temps à déboguer, mais peut-être est-ce plus facile à expliquer à votre responsable ? Si c'est le cas... trouvez un nouvel emploi ! Les tests sont essentiels pour améliorer votre confiance dans votre logiciel.
L'unittesting donne le plus de valeur lorsque vous avez beaucoup de code. Il est facile de déboguer un simple devoir à la maison en utilisant quelques classes sans unittesting. Une fois que vous serez dans le monde, et que vous travaillerez sur des bases de code de plusieurs millions de lignes, vous en aurez besoin. Vous ne pouvez pas tout simplement passez votre débogueur à travers tout. Vous ne pouvez tout simplement pas tout comprendre. Vous avez besoin de savoir que les classes dont vous dépendez fonctionnent. Vous devez savoir si quelqu'un dit "Je vais juste faire ce changement au comportement... parce que j'en ai besoin", mais il a oublié qu'il y a deux cents autres utilisations qui dépendent de ce comportement. Unittesting aide à prévenir cela.
Pour ce qui est de rendre la maintenance plus difficile : PAS QUESTION ! Je ne peux pas assez insister sur ce point.
Si vous êtes la seule personne à avoir travaillé sur votre projet, alors oui, vous pouvez penser cela. Mais ce sont des paroles en l'air ! Essayez de vous mettre à niveau sur un projet de 30k lignes sans unittests. Essayez d'ajouter des fonctionnalités qui nécessitent des changements significatifs au code sans unittests. Il y a pas de confiance que vous ne brisez pas les hypothèses implicites faites par les autres ingénieurs. Pour un mainteneur (ou un nouveau développeur sur un projet existant) les unittests sont essentiels. Je me suis appuyé sur les unittests pour la documentation, pour le comportement, pour les hypothèses, pour me dire quand j'ai cassé quelque chose (que je pensais sans rapport). Parfois, une API mal écrite a des tests mal écrits et peut être un cauchemar à changer, parce que les tests prennent tout votre temps. Un jour ou l'autre, vous voudrez remanier ce code et le corriger, mais vos utilisateurs vous en seront reconnaissants : votre API sera beaucoup plus facile à utiliser grâce à cela.
Une note sur la couverture :
Pour moi, il ne s'agit pas d'une couverture de test à 100%. Une couverture à 100% ne trouve pas tous les bogues, considérez une fonction avec deux if
déclarations :
// Will return a number less than or equal to 3
int Bar(bool cond1, bool cond2) {
int b;
if (cond1) {
b++;
} else {
b+=2;
}
if (cond2) {
b+=2;
} else {
b++;
}
}
Considérons maintenant que j'écrive un test qui teste :
EXPECT_EQ(3, Bar(true, true));
EXPECT_EQ(3, Bar(false, false));
C'est une couverture à 100%. C'est aussi une fonction qui ne respecte pas le contrat - Bar(false, true);
échoue, car il renvoie 4. La "couverture complète" n'est donc pas l'objectif final.
Honnêtement, je sauterais des tests pour BooksLimit()
. Il retourne une constante, donc cela ne vaut probablement pas la peine de les écrire (et il devrait être testé lors de l'écriture de DisplayBooks()
). Je serai peut-être triste lorsque quelqu'un décidera de calculer (incorrectement) cette limite à partir de la taille de l'étagère, et que celle-ci ne répondra plus à nos exigences. J'ai déjà été échaudé par l'expression "ne vaut pas la peine d'être testé". L'année dernière, j'ai écrit du code et j'ai dit à mon collègue : "Cette classe est principalement constituée de données, elle n'a pas besoin d'être testée". Elle avait une méthode. Il y avait un bug. Il a été mis en production. Il nous a bipé au milieu de la nuit. Je me sentais stupide. Alors j'ai écrit les tests. Et puis j'ai longuement réfléchi à ce qui constitue un code "ne valant pas la peine d'être testé". Il n'y en a pas beaucoup.
Donc, oui, vous pouvez sauter certains tests. Une couverture de test à 100 %, c'est bien, mais cela ne signifie pas par magie que votre logiciel est parfait. Tout se résume à la confiance face au changement.
Si je mets class A
, class B
y class C
ensemble, et que je trouve quelque chose qui ne fonctionne pas, est-ce que je veux passer du temps à déboguer les trois ? Non. Je veux savoir que A
y B
ont déjà rempli leurs contrats (via les unittests) et mon nouveau code en class C
est probablement cassé. Donc je le déteste. Comment puis-je savoir qu'il est cassé, si je ne le déteste pas ? En cliquant sur quelques boutons et en essayant le nouveau code ? C'est bien, mais pas suffisant. Une fois que votre programme passe à l'échelle, il sera impossible de réexécuter tous vos tests manuels pour vérifier que tout fonctionne correctement. C'est pourquoi les personnes qui utilisent unittest automatisent généralement aussi l'exécution de leurs tests. Dites-moi "Pass" ou "Fail", ne me dites pas "la sortie est ...".
OK, je vais aller écrire d'autres tests...