Blog Zenika

#CodeTheWorld

Web

TCR et l’extrême intégration continue

Dans un précédent article, j’ai présenté TCR et ai évoqué l’idée d’avoir un script qui tourne en fond pour faire de l’intégration continue.
Pour rappel, le script d’intégration continue est :

while true; do
    git pull --rebase && test && git push
done

Mais, pourquoi le script marche ?

Ce qui peut choquer dans ce script c’est la boucle infinie. On est constamment en train de vouloir faire un `git pull`. Ce qui veut dire que, pendant que je suis en train d’éditer mon code, j’essaie de m’intégrer avec mes collègues.
Avec une configuration git par défaut, `git pull` provoquera un merge avec ce que je suis en train de faire et ce qui a été commité. L’option `–rebase` transforme le merge en rebase ce qui permet d’avoir un historique plus linéaire, mais c’est un détail qui a peu d’importance dans cet article.
Dans la pratique, git n’acceptera de faire un pull que s’il n’y a aucun changement en cours. Dit autrement, quand tous mes changements sont commité. Par conséquent, le script ne s’exécute vraiment que quand j’ai commité mes changements.
Pour éviter d’avoir un script qui tourne en fond à ne rien faire et surtout pour rendre ce qui est implicite explicite, nous pouvons ajouter cela dans nos scripts `green.sh`

test && commit || revert
git pull --rebase && test && git push

et red.sh

test && revert || commit
git pull --rebase && test && git push

Mais dans le cas rouge, nous savons que nous ne ferons jamais un push, on peut donc le changer par :

test && revert || commit
git pull --rebase

L’avantage de cette fusion est une intégration continue poussée à son paroxysme. Je suis prévenu au plus tôt si j’ai un conflit avec un collègue.

Peut-on automatiser TDD ?

En y réfléchissant, si nous sommes capables de détecter à quelle phase de TDD nous sommes, alors nous sommes capables d’automatiser notre workflow de travail.
Or, c’est quelque chose où nous pouvons trouver une implémentation (naïve) rapidement : si nous avons ajouté un test depuis le dernier commit, alors nous sommes à l’étape rouge, sinon nous sommes soit à l’étage vert soit en refactoring.
On peut alors avoir un script du style :

if testJustAdded then
  red.sh
else
  green.sh
fi

Et voilà ! nous avons un script que nous pouvons lancer à chaque fois que nous pensons avoir passé une étape !

Et en vrai ? Ça donne quoi ?

J’ai eu l’occasion de tester ce workflow seul et à plusieurs.
Après un peu de pratique, le revert en cas d’erreur n’est plus désagréable et devient même un avantage. On se sent plus libre de “tester un truc pour voir”.
Retrouver mon étape rouge de TDD m’a permis de retrouver ma confiance dans mes tests.
Commiter quand mon code est rouge a été une grosse révélation pour moi. En effet, à ce moment-là, je n’ai écrit que mon test, mon message de commit ne peut donc que parler métier et non technique. Afin d’éviter de pousser des commits rouges, il suffit de faire un `–amend` lors du commit vert (ce qui est automatisable également, [cf le script complet] )
J’ai trouvé mes messages de commit inutiles à l’étape refactoring. J’ai alors testé une idée que je détestais par principe : ne pas mettre de message de commit. Jusqu’à présent, je n’ai pas trouvé de véritables inconvénients à cela.
Être alerté au plus tôt des conflits avec mes collègues a un bilan mitigé. La plupart du temps, c’est très agréable et permet de résoudre les conflits très rapidement (peu de code et c’est tout frais). Cependant, quand le conflit arrive quand nous venons d’ajouter un test rouge, cela peut provoquer une charge cognitive importante. En effet, à ce moment-là, nous avons deux problèmes à résoudre : le conflit et le test. J’ai personnellement trouvé que cela valait le coup, mais cela peut être déroutant au départ. Peut-être commençons-nous à toucher du doigt une limite à l’intégration continue ?
L’automatisation nous a posé des problèmes quand nous avons voulu nous appuyer sur le compilateur pour avancer. Il en va de même quand nous voulons raffiner le test que nous venons d’écrire. Le script avait tendance à supprimer notre code. Nous avons résolu ce problème en étant capables d’indiquer à notre script l’étape où nous sommes.
Enfin, nous avons codé dans un langage que nous ne maîtrisons pas beaucoup. Nous faisions souvent de l’exploration du langage. Dans ce cas-là, il est important d’avoir un REPL avec lequel nous pouvons explorer. Le script nous force à voir le code de production comme un sanctuaire où nous devons parfaitement maîtriser ce que nous faisons.

Conclusion

J’ai beaucoup aimé mes expériences avec TCR et je peux parfaitement m’imaginer travailler de cette manière sur un vrai projet (il faudra tout de même convaincre l’équipe 🙂 ).
Le channel TDD du slack “softwarecrafters” a été riche en échanges suite aux explorations de chacun. Je vous invite grandement à essayer ce workflow car, dans le pire des cas, cela vous fera vous poser des questions.

Auteur/Autrice

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.