Je suppose que mon projet est suffisamment découplé pour permettre des tests unitaires. Mais quelle taille, exactement, en termes de classes et de fonctions mon projet doit-il avoir pour que les tests unitaires en valent la peine?
Nous faisons tous des erreurs et personne n'est parfait, mais je me considère comme un programmeur décent pour gérer les erreurs des petits projets avec un pas en avant. Ou les tests unitaires sont-ils une nécessité absolue, quelle que soit la taille de votre projet?
D'après mon expérience, la classe one et la fonction one ont suffi pour prendre en compte la nécessité de tests unitaires.
class Simple {
boolean reallySimple() {
return true; // how do we make sure it doesn't change to false?
}
}
class SimpleTest {
void assertReallySimple() {
// ensure reallySimple return value isn't changed unexpectedly
UnitTestFramework.assertTrue(new Simple().reallySimple());
}
}
Je n'ai jamais adhéré à l'idée "vous devez tout tester à l'unité", bien qu'il y ait certainement des gens qui en ont (voir réponse de gnat !).
En ce qui me concerne, les principaux avantages des tests unitaires sont:
Fondamentalement, vous devez peser le temps qu'il vous faudra pour écrire et maintenir des tests par rapport à ces facteurs.
Le numéro 1 est généralement suffisant pour mériter la rédaction de tests. D'après mon expérience,> 95% du code est modifié tôt ou tard.
C'est simple: vous n'avez pas besoin de tests unitaires si vous supprimez le programme après l'avoir exécuté une fois.
Si cela vous semble excessif, réfléchissez à ce que l'alternative signifierait. S'il y avait une certaine taille en dessous de laquelle les tests unitaires ne paient pas, vous devriez continuer à juger dans votre esprit: "Ai-je encore atteint la taille magique? Dois-je commencer à écrire des tests?" Maintenant, les programmeurs sont notoirement mauvais pour prédire l'avenir, et ils sont notoirement mauvais pour juger de leurs propres compétences. Un code qui vous semble clair maintenant deviendra incompréhensible, même pour vous, même en attendant un mois. Un projet dont vous êtes absolument certain et positif ne sera plus jamais utilisé, et que vous garderez simplement sur la chance à distance que vous souhaitiez rechercher comment vous avez résolu quelque chose auparavant, sera être demandé à nouveau, et recevra des demandes de changement.
Il est donc très probable que vous vous trompiez sur l'utilité des tests, et lorsque vous commencez à avoir besoin de tests, vous n'êtes déjà pas sûr à 100% de la sémantique exacte à tester. Étant donné que je crois que tous les programmes exceptionnels, à l'exception de triviaux, bénéficient de tests unitaires, je considère que le coût des efforts consacrés aux tests qui ne sont plus jamais exécutés est négligeable par rapport aux risques d'étendre le code non testé et mal compris.
Il y a quelque temps, j'ai trouvé un bon article: Pourquoi les tests unitaires accélèrent le développement . Cela peut vous aider à répondre à la question.
... Et si la base de code ... était fournie avec un ensemble substantiel de tests unitaires. Un ensemble qui dirait: "si tous les tests réussissent, je garantis que le code fait toujours ce qu'il doit faire" et si un test échoue, il vous montre exactement où un comportement est cassé. C'est génial, je pourrais changer le code pour ajouter des choses que je veux sans errer si le code fait toujours ce qu'il devrait faire, je lance juste les ... tests et j'ai la foi. C'est un grand monde pour être ingénieur logiciel. J'ai remarqué que je pouvais avancer beaucoup plus vite ...
J'ai la "foi".
C'est probablement la raison la plus importante pour laquelle les tests unitaires accélèrent le développement dans un contexte d'entreprise.
Je peux croire que tout fonctionne toujours si tous les tests réussissent. Si les tests échouent, ils indiqueront exactement où se situe le problème ...
... vous devez avoir une couverture élevée des tests unitaires et de bons tests unitaires . Lorsque ces conditions sont respectées, vous vous retrouverez dans une situation où l'effort pour ajouter de nouvelles fonctionnalités est presque indépendant de la taille de l'application et qui à long terme accélérera développement .
Michael Feathers a présenté dans l'un de ses livres deux façons de travailler avec les changements de code:
Peu importe la taille de la base de code.
Selon Kent Beck dans sa réponse à la question Stack Overflow Quelle est la profondeur de vos tests unitaires? , vous devriez tester le code que vous avez tendance à vous tromper.
Si je ne fais généralement pas une sorte d'erreur (comme définir les mauvaises variables dans un constructeur), je ne le teste pas.
Des tests unitaires sont mis en œuvre pour gagner du temps et améliorer:
Il est indispensable d'écrire des tests unitaires pour des parties relativement complexes du programme.
Si vous êtes sûr que l'écriture de tests unitaires maintenant ne vous fera pas gagner de temps à l'avenir, vous pouvez l'ignorer. Cependant, vous ne savez jamais, et personnellement, je ne peux pas penser à un cas où il est moins cher (en termes de temps, d'argent et de nerfs) de ne pas écrire de tests unitaires mais de faire tous les tests manuellement à la place.
À moins que vous n'écriviez du code sans le tester, vous allez toujours encourir le coût des tests.
La différence entre avoir des tests unitaires et ne pas les avoir est la différence entre le coût d'écriture du test et le coût de son exécution par rapport au coût du test à la main.
Si le coût de l'écriture d'un test unitaire est de 2 minutes et le coût de l'exécution du test unitaire est pratiquement 0, mais le coût du test manuel du code est de 1 minute, alors vous atteignez le seuil de rentabilité lorsque vous avez exécuté le test deux fois.
Pendant de nombreuses années, je pensais à tort que je n'avais pas assez de temps pour écrire des tests unitaires pour mon code. Quand j'ai fait des tests, ils étaient gonflés, des choses lourdes qui m'ont seulement encouragé à penser que je ne devrais jamais écrire des tests unitaires que lorsque je savait ils étaient nécessaires.
Récemment, j'ai été encouragé à utiliser Test Driven Development et j'ai trouvé que c'était une révélation complète. Je suis maintenant fermement convaincu que je n'ai pas le temps pas pour écrire l'unité- tests.
D'après mon expérience, en développant en gardant à l'esprit les tests, vous vous retrouvez avec des interfaces plus propres, des classes et des modules plus ciblés et généralement plus SOLID , du code testable.
Chaque fois que je travaille avec du code hérité qui n'a pas de tests unitaires et que je dois tester quelque chose manuellement, je continue de penser "ce serait tellement plus rapide si ce code avait déjà des tests unitaires". Chaque fois que je dois essayer d'ajouter une fonctionnalité de test unitaire au code avec un couplage élevé, je continue de penser "ce serait tellement plus facile s'il avait été écrit de manière découplée".
TL; DR version:
Écrivez un test lorsque le coût de l'écriture du test, plus le coût de son exécution autant de fois que nécessaire, sera probablement inférieur au coût du test manuel autant de fois que vous besoin.
N'oubliez pas que si vous utilisez TDD, le coût d'écriture des tests est susceptible de diminuer à mesure que vous vous améliorez, et à moins que le code ne soit absolument trivial, vous finirez probablement par exécuter vos tests plus souvent que prévu.
Testez dès que vous observez les régressions ou la peur qui en provoque avec vos modifications et sans vous en rendre compte.
Kindle qui a peur, laissez-le atteindre une taille adéquate: plus tôt vous testez, mieux c'est.
Veuillez noter: selon votre rôle dans le projet, les tests unitaires peuvent ne pas être le seul type de tests que vous souhaitez écrire.
Tout le monde est à juste titre obsédé par les tests unitaires , en raison des mauvaises pratiques de test traditionnelles dans le passé; mais si vous n'avez jamais testé auparavant, vous devriez vraiment vous concentrer sur les tests en général , les tests unitaires ne vont pas à eux seuls résoudre les problèmes du monde.
"Dois-je faire un test unitaire" peut généralement être répondu en répondant à la question suivante: "Est-il important que cette fonction fonctionne correctement et est-il important pour moi de savoir quand elle cesse de fonctionner?"
Bien sûr, c'est beaucoup plus compliqué que cela, mais c'est une bonne façon de commencer. Finalement, vous évaluerez également si le code est déjà testé en raison de son utilisation dans une autre fonction, ou si votre temps serait mieux utilisé dans une autre fonction, etc.
Je crois que ce n'est pas la taille du projet mais le type de projet qui décide s'il doit utiliser des tests ou non.
Si vous travaillez sur une preuve de concept ou sur un autre projet dont le but est d'apprendre du codage, les tests ne sont pas nécessaires. Si le projet est destiné à être utilisé, peut-être même envoyé en production, il doit être testé.
Une citation de "Clean Code" de Robert C. Martin : "Si c'est trivial d'écrire, c'est trivial de tester", donc il n'y a aucune excuse pour sauter le test des programmes courts et triviaux.
Ce n'est vraiment pas une question de taille - c'est ce que vous en faites (et quel âge il a). Si je cherche à comprendre comment fonctionne une technologie et que je prévois de jeter la chose (nous appelons cela un pic dans Scrum), je vais simplement coder sans faire beaucoup de tests. Si vous prévoyez de le développer davantage (même si vous êtes juste en train de nouiller), vous devez écrire des tests autour du code. TDD est une technique de conception avant même d'être une technique de test. Vous voulez avoir une image claire de ce que vous voulez que le code fasse avant de vous lier aux détails de l'exécution. Je voudrais également PAS recommander d'essayer d'écrire des tests unitaires étendus autour de grandes quantités de code hérité. Essayez d'identifier les parties qui sont complexes (qui ont une grande complexité cyclomatique/sensation de code spaghetti pour elles) et les parties qui échouent fréquemment (elles seront souvent les mêmes). Comme d'autres l'ont suggéré, j'irais lire le livre de Kent Beck sur TDD et certainement lire le livre de Michael Feather. Ce qu'ils ne couvrent pas beaucoup, c'est l'aspect politique de l'écriture de tests unitaires autour du code. Beaucoup de développeurs détestent devoir modifier leur code pour le rendre testable, et beaucoup de développeurs ne ressentent pas du tout le besoin de tester le code. C'est quelque chose sur lequel nous devons travailler en tant que profession. Toutes les autres disciplines du génie doivent prouver (souvent mathématiquement) que leur travail répond aux spécifications. Nous devons faire de même.