Pratiques avancées des tests avec Nathaniel Richand
(Type : audio sur diaporama sous forme de video)Nathianel attaque fort avec 2 qestions qui interpellent (tests des messages dans les exceptions et des messages dans les logs), en rappellant qu'il faut rester pragmatique selon le contexte !
Outre le TDD evidemment très intéressant, Nathianel évoque les tests qui vieillisent mal (notamment par la mise en commentaire des vérifications "assert"), et le fait que le TDD peut devenir un frein en augmentant la rigidité du code.
Il propose donc 2 axes pour éviter cela :
- augmenter la lisibilité
- diminuer la fragilité
Pour augmenter la lisibilité :
- choisir des noms explicites pour les méthodes de tests en donnant le contexte et l'intention
- ne pas masquer les informations utiles, qui peuvent par exemple venir de fichiers XML non visibles dans le code de test (cf DBUnit ou Unitils)
- masquer tout ce qui est inutile en utilisant les Setup, les Teardown, les import static, du code "Fluent interface" avec le pattern builder, etc ...
- éviter les "try/catch" avec "fail()" en remontant simplement les potentiels exceptions (throws sur les méthodes de tests) idem pour les "if/else" avec "fail()"
- éviter les messages explicites en début d'assert en utilisant des tests natifs ou des bibliothèques favorisant l'affichage les messages d'erreur (cf FestAssert)
- éviter des nombres et textes dans le code de test, utiliser des constantes, y compris pour des paramètres à null
- garder la même structure pour tous les tests, comme par exemple "Given/when/then" proposé par Nathianel, ou plus perso pour moi, "Préparations/Tests/Vérifications", ce qui a en autre l'avantage de pousser le développeur à ne faire qu'un test par méthode
- soigner ses assertions, notamment en utilisant les bons assert ("assertEquals" plutot que "assertTrue") et les librairies comme Festassert ou armcrest
- utiliser Spock, dont j'ai déjà parlé dans un précédent poste et qu'il va vraiement falloir que je teste !
Remarque "évidente" (...) en passant : si les tests sont compliqués, c'est que potentiellement, le code est ... compliqué ! A méditer ...
Pour rendre les tests plus robustes :
- pas de duplication de code (utiliser des fixtures, des builders, des assertions "maison", ...)
- tester un comportement à un seul endroit
- éviter la réflexion (reflect java pour tester des méthodes privées ..... bahhhhhhhh)
[NDLA] Sur ce point, je n'approuve pas l'idée de changer la portée "private" d'une méthode pour la tester, il y a d'autre solutions, notamment un changement d'architecture pour extraire cette méthode dans une autre classe testée unitairement ... éternet débat ? ...
- adapter ses tests selon que le code est bas niveau (basique) ou haut niveau (interaction entre plusieurs collaborateurs), utiliser des mocks pour vérifier le comportement global de la méthode
Je note l'idées intéressante consistant à ajouter au TDD un étape après l'étape "rouge" pour vérifier les messages d'erreurs et les rendre explicites.
Je recommande moi aussi le livre "Clean code" de Robert C. Martin traduit en Français sous le titre "Coder proprement" dont la première moitié est tout simplement pleine de bon sens !
S'en est suivi une séance de Questions/Réponses sur différents sujets :
- tests sur environnement de prod : plutôt éviter (selon contexte) !
- tests des classes abstraites : Nathianel évoque la possibilité pour le code de test d'hériter du code de test de la classe abstraite
[NDLA] Perso, j'utlise de moins en moins l'héritage et les classes abstraites, et de plus en plus l'aggrégation ;-) donc la question ne se pose plus ...
- alternatives à DBUnit : mocker les DAO, ou sur-couche DBUnit pour éviter les fichiers XML (DBUnit et Unitils n'étant plus maintenus)
Sur l'utilisation de mocks, mon approche est très différente de Nathianel qui dit les utiliser peu. Je développe depuis pas mal de temps de façon très découpée pour respecter le principe "1 classe - 1 role", et beaucoup de base d'interfaces et de collaborateurs. J'utilise donc énormément les mocks pour simuler et maitriser le comportement de chaque collaborateur pour que le test ait tout son sens, et je n'ai jamais rencontré de grandes difficultés lors d'évolutions et refactorings de code, du moins rien à voir avec l'apport d'une telle architecture !
En tout cas, une présentation intéressante, efficace, et que j'approuve entièrement, aux détails près mentionnés précédemment ;-)
2011 nri-pratiques tests-avancees
View more presentations from Nathaniel Richand