Quelque chose que j'ai remarqué récemment, c'est quand je fais les types de projets suivants:
- Au début d'un projet
- Travailler sur un MVP / prototype
- Ajout de fonctionnalités qui ne sont pas entièrement définies
- Travailler sur un projet à plus petite échelle
Pour référence, je travaille actuellement sur un projet Python qui contient actuellement environ 1k lignes de code, y compris certains commentaires et tous les espaces.
Je trouve qu'il est extrêmement facile d'écrire d'abord des tests d'intégration, de travailler sur le code, puis une fois que l'API est quelque peu durcie, travailler sur l'ajout de tests unitaires. Les types de tests que je peux exécuter sur ma main
fonction, pour ainsi dire, et sont plus "de bout en bout" qu'autre chose.
En effet, les tests unitaires sont vraiment ennuyeux lorsqu'une API change assez rapidement, ce qui est souvent le cas lorsque vous travaillez sur un projet correspondant à l'un ou à la plupart des critères ci-dessus.
Cette approche est-elle une bonne approche et quels sont les critères à prendre en compte pour décider de commencer par des tests unitaires ou d'intégration en premier pour ces types de projets? Est-ce que je manque la valeur des tests unitaires de ces types de projets avant que les API ne soient plus solides?
la source
Réponses:
Non, tu vas bien.
Les deux grands objectifs du TDD sont:
La couverture des tests peut être assez bien maximisée dans tous les cas. Autrement dit, que vous testiez d'abord de petites unités isolées ou de grandes unités «intégrées», vous avez la possibilité d'écrire vos tests avant vos implémentations.
Ce que vous gagnez en écrivant des tests de niveau supérieur («intégration») en premier lieu, comme vous le faites, c'est l'assurance que vos interfaces et interactions de niveau supérieur sont également définies principalement en fonction de leur utilisation, plutôt que par leurs implémentations internes.
Le même effet peut être obtenu en grande partie avec une bonne "architecture" et un bon diagramme. Mais, ces tests de haut niveau peuvent souvent révéler des choses que vous avez manquées dans vos diagrammes - ou que vous vous êtes juste trompés dans votre travail «d'architecture».
Si vous ne faites pas de TDD (ou quelque chose du genre), l'ordre dans lequel vous écrivez les tests n'a pas beaucoup d'importance. Les interfaces existent déjà au moment où vous testez, il est donc beaucoup moins probable que vos tests changent quoi que ce soit - ils ne serviront qu'à vous protéger contre des changements de rupture particuliers.
Mais, si vous souhaitez construire l'implémentation de haut en bas ou de bout en bout, la première puce s'applique toujours dans une large mesure. Le code de haut niveau permet de définir des interfaces de bas niveau. Alors que, si les interfaces de bas niveau sont écrites en premier (ou sinon existent déjà), le code de haut niveau est à leur merci ...
1. Celui-ci s'applique également même si vous ne faites pas de TDD complet. Même si vous écrivez juste 1 ou 2 tests avant votre implémentation, ces 1 ou 2 tests peuvent vous aider à définir ou affiner vos interfaces avant qu'il ne soit trop tard!
la source
J'ai travaillé comme tu travailles. Et je ne vais pas vous dire que vous ne pouvez pas. Je vais vous avertir de quelque chose que vous pourriez rencontrer.
Lorsque chaque test unitaire est simplement une modification, il est difficile d'apprendre à les rendre flexibles. Ils ont tendance à n'être rien de plus que des tests de régression. Comme vous ne les avez jamais utilisés pour vous aider à refactoriser, il est très facile d'écrire les types de tests qui rendent la refactorisation plus difficile. Cela a tendance à devenir incontrôlable jusqu'à ce que vous perdiez toute confiance en TDD.
Cependant, vous travaillez déjà sur quelque chose. Je ne vais pas te dire d'arrêter. Je dirai que cela vaut la peine de commencer autre chose que vous avez le temps d'explorer et de suivre le cycle de refactorisation rouge vert depuis le début. Assurez-vous que vous utilisez réellement les tests pour vous aider à refactoriser. Jusqu'à ce que vous maîtrisiez cette façon de travailler, utilisez-la avec parcimonie sur quelque chose qui compte. C'est une façon très différente de coder et il faut s'y habituer. Le faire à mi-chemin ne fera du bien à personne.
Cela dit
Comprenez qu'un test unitaire n'est PAS simplement un test qui agit sur une classe. Tant que l'API sur laquelle vous travaillez peut être testée sans effectuer l'une des opérations suivantes, vous effectuez très bien les tests unitaires:
Donc, si votre test de bout en bout implique plus d'un objet, ça va. Il s'agit de tests unitaires et non de tests d'objets.
Tout comme les méthodes privées n'ont plus besoin d'être testées, elles sont testées en testant les méthodes publiques qui les utilisent, les objets n'ont pas besoin d'être initialement développés sous leur propre harnais de test. Ce n'est que lorsque les objets sont envisagés pour une utilisation indépendante de l'histoire de bout en bout qu'ils doivent vraiment être traités comme s'ils avaient leur propre interface et comportement à confirmer. Si vous faites attention à ce sujet, c'est lorsque vous rendez ces objets publics. De cette façon, vous ne faites aucune promesse que vous n'avez pas testée.
la source