Refactoriser les tests unitaires?
Lorsque nous travaillons avec du code hérité et que nous devons apporter des modifications, nous écrivons d'abord des tests sur le comportement actuel. De cette façon, nous pouvons mettre en œuvre de nouveaux changements en toute confiance. Nous pouvons même refactoriser le code.
Le code hérité est souvent un mauvais code, et après une certaine refactorisation, le code peut être plus simple, plus facile à tester. Puisque le refactor a été validé par les tests, devrions-nous également refactoriser les tests si nous pouvons les rendre plus simples / plus clairs ou les conserver tels qu'ils ont été écrits?
Réponses
Les tests automatisés sont du code, il est donc logique de maintenir ce code, y compris de refactoriser les tests le cas échéant. Toutefois:
le code productif et les tests ont des exigences de qualité différentes
- n'investissez pas de temps dans des choses qui n'ont pas d'importance
le code productif doit avoir une seule source de vérité, tandis que les tests doivent être largement autonomes
- la duplication n'est pas forcément mauvaise
Et comme le souligne Ewan, vous ne devriez jamais changer le code et les tests en même temps. Ensemble, code + tests constituent un système d'auto-test. Un changement dans une partie est vérifié en l'exécutant avec l'autre partie. Changer les deux en même temps renonce à cette sécurité. Ce n'est pas toujours possible dans la pratique (par exemple lors de la modification d'une préoccupation transversale telle qu'une bibliothèque standard sous-jacente), mais il serait insensé d'abandonner cette sécurité sans un besoin très fort.
Raisons courantes pour lesquelles j'ai refactoré les tests, sans ordre particulier: l'API testée avait changé, le passage à une approche de test différente (par exemple, tests basés sur des scénarios vs tests basés sur des propriétés, tests au niveau de l'API vs tests au niveau du comportement) cadre de test (par exemple pour obtenir de meilleurs rapports d'échec ou pour utiliser des tests paramétrés), changer l'organisation de test (par exemple, suites et cas de style xUnit vs style RSpec describe – it), se débarrasser de la duplication accumulée (par exemple extraire du code commun pour créer un appareil) ,…
Lorsque nous travaillons avec du code hérité et que nous devons apporter des modifications, nous écrivons d'abord des tests sur le comportement actuel. De cette façon, nous pouvons mettre en œuvre de nouveaux changements en toute confiance. Nous pouvons même refactoriser le code.
Cela peut parfois refléter votre processus de travail, mais d'après mon expérience, un processus plus efficace est:
vous écrivez des tests
vous refactorisez pour faciliter le changement
vous implémentez le changement
De cette façon, il devient plus évident que vous refactorisez quand il y a une vraie raison pour un changement , pas seulement parce que le code "n'est plus propre".
Essayez maintenant d'appliquer les mêmes mesures à vos tests: vous ne refactorisez pas vos tests car "ils ne sont plus propres" . Vous les refactorisez lorsqu'ils commencent à vous empêcher d'apporter des modifications faciles à votre code existant.
Par exemple, lorsque vous avez dix tests qui appellent tous la même méthode publique d'une classe sous tests, alors que dans votre code de production cette méthode publique n'est appelée qu'à un seul endroit, il s'agit d'une forme de duplication de code par des tests qui peut vous empêcher de changer la signature de cette méthode publique.
Je le laisserais généralement ainsi à moins que vous n'obteniez vraiment l'exigence de ce dernier, ou plus général: lorsque vous remarquez cette duplication de code vous oblige à apporter la même modification à vos tests à plusieurs endroits.
Vous voudrez peut-être commencer par refactoriser les tests.
Les tests capturent ce que fait l'ancienne application; une sorte de documentation. Les tests vous indiquent l'entrée et la sortie, le code vous indique le processus. Si les tests sont mauvais, les ranger (en fonction de leur gravité) vous aidera à comprendre le code.
C'est aussi un excellent moyen de juger si les tests ajoutent de la valeur; un système hérité sur lequel j'ai travaillé avait une excellente couverture de code, mais lors de l'inspection, les tests affirmaient des choses inutiles ... comme s'assurer que Getters et Setters fonctionnaient (tester le framework .NET pas l'application).
Une fois que vous avez obtenu un test propre, vous aurez une meilleure compréhension du code, puis vous pourrez prendre de meilleures décisions sur la façon de refactoriser le code.