Contrairement aux autres réponses, il est important de noter que certaines méthodes de test peuvent devenir fragiles lorsque le système sous test (SUT) est refactorisé, si le test est en boîte blanche.
Si j'utilise un framework de mocking qui vérifie l' ordre des méthodes appelées sur les mocks (lorsque l'ordre n'est pas pertinent car les appels sont sans effet secondaire); puis si mon code est plus propre avec ces appels de méthode dans un ordre différent et que je refactorise, alors mon test se cassera. En général, les simulations peuvent introduire de la fragilité dans les tests.
Si je vérifie l'état interne de mon SUT en exposant ses membres privés ou protégés (nous pourrions utiliser "friend" dans Visual Basic, ou augmenter le niveau d'accès "internal" et utiliser "internalsvisibleto" en c #; dans de nombreuses langues OO, y compris c # une " sous-classe-test-spécifique " pourrait être utilisée), puis soudainement l'état interne de la classe importera - vous pouvez refactoriser la classe en boîte noire, mais les tests en boîte blanche échoueront. Supposons qu'un seul champ soit réutilisé pour signifier différentes choses (ce n'est pas une bonne pratique!) Lorsque le SUT change d'état - si nous le divisons en deux champs, nous devrons peut-être réécrire des tests défectueux.
Les sous-classes spécifiques aux tests peuvent également être utilisées pour tester des méthodes protégées - ce qui peut signifier qu'un refactorisateur du point de vue du code de production est un changement radical du point de vue du code de test. Déplacer quelques lignes dans ou hors d'une méthode protégée peut ne pas avoir d'effets secondaires sur la production, mais casser un test.
Si j'utilise des " hooks de test " ou tout autre code de compilation spécifique au test ou conditionnel, il peut être difficile de s'assurer que les tests ne se cassent pas en raison de fragiles dépendances de la logique interne.
Ainsi, pour éviter que les tests ne se couplent aux détails internes intimes du SUT, cela peut aider à:
- Utilisez des talons plutôt que des simulacres, si possible. Pour plus d'informations, consultez le blog de Fabio Periera sur les tests tautologiques et mon blog sur les tests tautologiques .
- Si vous utilisez des simulations, évitez de vérifier l'ordre des méthodes appelées, sauf si cela est important.
- Essayez d'éviter de vérifier l'état interne de votre SUT - utilisez si possible son API externe.
- Essayez d'éviter la logique spécifique au test dans le code de production
- Essayez d'éviter d'utiliser des sous-classes spécifiques au test.
Tous les points ci-dessus sont des exemples de couplage en boîte blanche utilisés dans les tests. Donc, pour éviter complètement de refactoriser les tests de rupture, utilisez les tests de boîte noire du SUT.
Avertissement: Pour discuter de la refactorisation ici, j'utilise le mot un peu plus largement pour inclure la modification de l'implémentation interne sans aucun effet externe visible. Certains puristes peuvent être en désaccord et se référer exclusivement au livre Refactoring de Martin Fowler et Kent Beck - qui décrit les opérations de refactoring atomique.
Dans la pratique, nous avons tendance à prendre des étapes incessantes légèrement plus importantes que les opérations atomiques décrites ici, et en particulier les modifications qui laissent le code de production se comporter de manière identique de l'extérieur peuvent ne pas laisser passer les tests. Mais je pense qu'il est juste d'inclure "un algorithme de remplacement pour un autre algorithme qui a un comportement identique" en tant que refactor, et je pense que Fowler est d'accord. Martin Fowler lui-même dit que le refactoring peut casser les tests:
Lorsque vous rédigez un test simulateur, vous testez les appels sortants du SUT pour vous assurer qu'il parle correctement à ses fournisseurs. Un test classique ne se soucie que de l'état final - pas de la façon dont cet état a été dérivé. Les tests mockistes sont donc davantage couplés à la mise en œuvre d'une méthode. Changer la nature des appels aux collaborateurs provoque généralement la rupture d'un test de simulation.
[...]
Le couplage à l'implémentation interfère également avec le refactoring, car les changements d'implémentation sont beaucoup plus susceptibles de casser les tests qu'avec les tests classiques.
Fowler - Les simulacres ne sont pas des talons