Il faut du courage pour développer, des tests qualitatifs à la rescousse

Paysage calme

Réflexions personnelles à partir de 4 situations arrivées il y a quelques temps

Le postulat qui part des théories de l’Extreme Programming, mais aussi de mon vécu personnel, est le suivant : il faut du courage pour développer.

Il me faut du courage pour :

  • Rentrer la première fois dans une application
  • Construire une application au fur et à  mesure sans régression
  • Ajouter une nouvelle fonctionnalité à  une application déjà existante sans régression
  • Refactorer du code

Et pour avoir ce courage, il faut de la confiance !

Alors bien sûr, il y a des pratiques qui me permettent d’avoir cette confiance :

Pas de code spaguetti Clin d'oeil

Feature branching

Chaque développeur travaille sur sa branche qui n’est mergée qu’à la toute fin.

Il ne risque pas de détruire l’ensemble du code et ne prend pas peur quand il se rend compte qu’il a tout cassé lorsqu’il effectue un push avec son système de versionning préféré Smiley souriant.

Système de relecture par ses pairs

Une vérification même purement technique m’apporte du courage parce que mes pairs m’aident à  m’assurer que mon code est maintenable, lisible, …

C’est un système qui de plus me pousse à rechercher le code parfait que tout le monde comprendrait du premier coup d’œil (bon après entre le désir et la réalité, c’est autre chose malheureusement Clin d'oeil).

Pair programming

Le pair programming apporte du courage parce qu’il est toujours plus évident de se confronter à un problème avec quelqu’un d’autre.

Et puis il y a les tests unitaires, mes préférés. Et si tester, c’est douter …

le doute, c’est le début de la sagesse (Aristote).

L’absence de tests ou la non pertinence de tests me fait peur

chat apeuré

Je pars là  de 4 situations qui me sont arrivées il y a quelques temps (dont je l’avoue j’ai parfois malheureusement aidé à se construire) et qui m’ont fait réfléchir sur cette notion de courage

  • Ajout de fonctionnalités dans une application inconnue sans test => Peur
  • Ajout de fonctionnalités dans une application avec une bonne couverture de tests, mais qui présente des tests vérifiant que les méthodes ne cassent pas, mais pas forcément ce qu’elles sont censées faire => Peur
  • Refactoring d’une fonctionnalité sans test dans une application plus ou moins testée => Peur
  • Refactoring dans une application testée, mais où les tests durent longtemps (à partir de 5 minutes, j’avoue devenir fébrile Smiley souriant) => Pas peur, mais perte de courage quand même

Là oui dans ces 4 situations, je considère que les tests sont la cause d’une perte de confiance.

Comment je pense que des tests m’auraient apporté plus de confiance et donner du courage dans ces 4 situations ?

  • Des tests comme documentation pour entrer plus sereinement dans un projet
  • Un contrôle sur ce qu’on ajoute et une manière d’éviter les régressions et d’oser tout casser, tout recommencer, …

Comment je pense que des tests plus qualitatifs m’auraient apporté plus de confiance et donner du courage dans ces 4 situations ?

  • Un bon code coverage

Si les tests ne couvrent qu’une partie moyenne du code, comment savoir si on n’impacte pas une partie qui n’est pas couverte ?

  • Des tests pertinents

Des tests qui se contentent de passer dans l’ensemble du code et d’augmenter le score de code coverage ne m’aident pas à avoir du courage.

Ils doivent être pertinents et permettre de tester vraiment ce qu’est censé faire le code pour que je me sente bien.

  • Rapidité

Les tests doivent s’exécuter rapidement.

S’ils mettent trop de temps, je (comme beaucoup de développeurs je pense) rechigne à les lancer souvent et n’ose que difficilement m’aventurer à du refactoring ou d’autres choses qui pourraient casser le code.

Make it work, make it right, make it fast (Kent Beck)

Quelles solutions j’ai pu rencontrer pour éviter ce genre de situations ?

  • Contrôler le code coverage au fur et à mesure

Sans obsession pour un score de code coverage, j’aime avoir une vue au fur et à mesure de ce que je teste.

  • Quand il y a un bug non perçu par les tests, j’ajoute un test le plus immédiatement possible pour ne plus jamais tomber dans cette régression
  • Contrôler automatiquement la qualité de ses tests avec un framework de mutation testing

Récemment, j’ai découvert le concept de mutation testing et d’Humbug :

Il s’agit d’outils qui :

  1. créeent des variations d’un code métier, variations appeées « mutants »
  2. lancent les tests unitaires sur ces mutants (Les frameworks mutants ou comment évaluer la qualité de ses tests unitaires)

J’ai testé Humbug sur mes petits projets personnels et j’ai bien aimé ce que l’outil m’a apporté.

Cependant, je ne sais pas trop ce que peut donner ce genre d’outils sur des projets plus importants. Il m’apparaît qu’ils restent lourds à exécuter et que lancer Humbug ne doit pas se faire après chaque changement de la base de code, mais peut-être une fois par jour.

  • L’utilisation du TDD/BDD

Le fait de penser à mes tests avant (TDD) me permet de contrôler de manière plus pertinente mon code coverage, l’idée étant que tout code répond à un cas de test.

Puis en écrivant le minimum de test pour que ça plante et le minimum de code pour que ça passe, ça m’oblige à voir les faiblesses de mes tests et à les rendre plus robustes. Ils sont plus adaptés à ce que je développe.

Et j’essaye de donner un peu plus de behavior à mes tests (BDD) pour les rendre plus compréhensibles et plus pertinents parce qu’après tout je me dis que mes tests ont un sens un peu plus que technique puisqu’ils sont censés refléter mon application et donc un métier.

  • Micro-services

En fait ce que m’apportent les services, c’est de séparer les éléments les uns des autres et de pouvoir ainsi exécuter des séries de tests plus courtes et donc plus rapides.

  • Mocks

En mockant les dépendances de mes tests, ceux-ci s’exécutent plus rapidement.

Ils sont plus unitaires et j’ai un meilleur contrôle sur ce que je veux tester. Je peux par exemple plus aisément tester des cas d’erreurs.

  • Séparation tests fonctionnels/tests unitaires

Parce que je pense que les tests fonctionnels aussi sont importants, qu’ils permettent de tester un ensemble de notre application avec une vraie base de données et que du coup ils m’aident à avoir confiance, … mais qu’ils sont longs à s’exécuter, j’apprécie quand ils sont séparés des tests unitaires.

Comment j’essaye de m’en sortir dans ces situations ?

J’essaye d’utiliser la politique du scout que décrit Robert C Martin dans son livre Clean code et qu’on pourrait résumer ainsi :

Prière de laisser cet endroit plus propre qu’en y entrant

Je pense que ça passe aussi par les tests. Donc au fur et à mesure, quand je modifie une fonctionnalité, j’essaye de penser aux tests qui y sont associés et à les améliorer ou les compléter s’il y a lieu d’être.

J’essaye d’avancer en retrouvant la sérénité dont j’ai besoin pour développer sans peur.

Paysage calme