Je suis un pratiquant de développement axé sur les tests depuis plusieurs années et que dans l'ensemble, je suis content de cela. L'idée que je ne comprends pas encore est l'idée que vous devriez toujours être unitaire testant la «plus petite unité possible». P>
Une partie de l'idée des tests unitaires semble être de vous permettre de refractant avec confiance que vous ne briserez rien. Cependant, je trouve que les tests qui testent de très petits morceaux de code ne survivront presque jamais à ces refacteurs, le code change toujours assez de manière significative que de petits tests d'unité ne sont que jetés et de nouveaux tests sont écrits. Ce sont les tests qui couvrent de plus grandes fonctionnalités qui semblent donner la plus grande valeur ici, car les interfaces de niveau supérieur ne changent pas aussi souvent. P>
et pour les refacteurs triviaux, comme les méthodes de déménagement autour, celles-ci ne sont que faites via une IDE et que j'utilise un langage saisi de manière statique, je n'ai jamais rencontré une situation où l'IDE n'est pas en mesure de faire le refactoring parfaitement. p>
Quelqu'un d'autre a des expériences similaires ou opposées? P>
6 Réponses :
C'est une question de granularité, comme Goldilocks et les trois ours. Vous voulez quelque chose qui n'est pas trop petit, pas trop grand, mais juste à droite. P>
Si la granularité est trop petite, vous avez peut-être pu constaté que c'est une perte de temps. S'il est trop important, il peut manquer de contraintes importantes qui doivent rester constantes sur un refactoring / reconfiguration, etc. P>
Comme toute "meilleure pratique", ces idées sont souvent développées en théorie mais nécessitent un sens commun et une adaptation à votre situation particulière pour vous être utile. p>
J'ai trouvé la même chose - mais une chose que je pense est importante à différencier est entre des unités de code privées et des unités de code accessibles publiquement. Je pense qu'il est important de toujours tester la «plus petite unité possible utilisable du code exposé dans l'API publique». P>
L'API publique ne devrait pas changer lors des refacteurs (puisqu'il brise la compatibilité binaire et les versions), ce problème existe donc. P>
Quant à l'API privé, il y a un équilibre ici. Plus vous testez, plus vous pouvez compter sur vos tests. Le niveau supérieur de vos tests deviennent, plus les tests sont flexibles, et plus ils sont susceptibles de survivre à un refactoring. P>
Cela étant dit, je crois que les deux sont importants. Un refactoring à grande échelle nécessitera toujours des tests de retouche - qui fait partie des tests en général. P>
me semble que la plus petite unité de code est testée, plus vous obtenez d'informations sur les échecs de test. Si vous avez un test de niveau supérieur qui couvre un morceau de code plus important, une échec vous en dira moins sur l'endroit où le problème est. P>
Et alors? Les échecs de test sont un événement relativement rare - je ne vois pas le temps investi dans la maintenance des microtestes en payant vraiment.
Assez juste. Je veux dire, il y a certainement un point de rendement décroissant.
La plupart des temps, je ne fais que tester les classes et méthodes publiques. Parce que je pense que, comme vous l'avez dit, les membres privés sont trop volatils et sujets à des changements. P>
Une modification sur les membres privés et internes indique que vous modifiez l'algorithme intérieur, alors qu'une modification des membres publics indique une modification sémantique. Si je pense que changer un membre privé changer la sémantique de ma classe, alors, peut-être que ce membre ne devrait peut-être pas être privé après tout. P>
Un bug introduit lors du refactoring de l'algorithme interne de votre classe défère 90% des tests de temps au niveau sémantique, et la plupart du temps, si vous testez souvent et tôt, le bogue se trouve rapidement. P >
Ça ne sonne pas comme si vous faites du vrai Développement axé sur les tests , Ce qui nécessite un cycle itératif d'écrire un test pour un petit morceau de fonctionnalité, créant ainsi la fonctionnalité pour satisfaire le test, puis refactoring pour supprimer toute duplication que le test / code peut avoir ajouté. On dirait que vous testez après le fait («le code change toujours suffisamment de manière significative que les petits tests de l'unité sont juste éloignés»). Si un test est une spécification de fonctionnalité (tel qu'il est dans TDD), le refactoring ne ferait jamais un test de «ne pas survivre». P>
Ainsi, en supposant que vous ne faites pas vraiment TDD, vous avez des difficultés avec le compromis de la quantité de code de test à écrire par rapport à combien de temps à dépenser du code de production. Je dirais, écrivez suffisamment de code de test pour savoir que votre code fait ce qu'il est censé faire. Si vous pouvez le faire avec des tests plus grossièrement grains, c'est bien, bien que d'autres l'ont dit, cela rend plus difficile de savoir ce qui cause une défaillance. P>
Le test n'est pas seulement pour le refactoring. C'est de savoir quand vous avez terminé. C'est ainsi que vous pouvez ajouter de nouvelles fonctionnalités en toute confiance, vous ne briserez pas l'ancien. C'est donc après que vous soyez depuis longtemps, quelqu'un d'autre peut entrer et comprendre votre code, le changer et être confiant cela fonctionne. P>
Je vous recommande de suivre la pratique TDD comme décrit par Kent Beck . Écrire des tests après que le fait soit meilleur qu'aucun test, mais je trouve une pratique beaucoup moins productive que TDD. P>
Je suis en train de suivre davantage une approche BDD, où je finis pas à tester les fonctionnalités autant que les résultats. Ce faisant, vous testez toujours des fonctionnalités mais mesurées par les résultats attendus. Je trouve que cela rend votre test plus significatif, moins fragile, plus applicable, et je finis par écrire moins d'entre eux. P>