Un client m’appelle pour un bug de facturation sur un ERP interne (le logiciel maison qui gère sa gestion : ventes, stocks, compta) d’une dizaine d’années. Aucun test nulle part. Je corrige la ligne fautive, je livre, et trois jours plus tard un export comptable sort faux : ma correction avait un effet de bord deux modules plus loin, invisible depuis l’endroit que je touchais. Voilà le vrai danger du legacy non testé. Ce n’est pas le bug que vous voyez, c’est celui que vous créez en réparant le premier.
La tentation, à ce stade, c’est de tout couvrir avant de retoucher quoi que ce soit. Mauvaise piste.
Sur une base héritée sans tests, on commence par des tests de caractérisation : ils figent ce que le code fait aujourd’hui, sans juger si c’est juste. À la moindre régression, ils sonnent. C’est ça qui rend les modifications sûres.
Pourquoi « tout tester d’abord » ne marche jamais
Sur une grosse base sans tests, exiger une couverture complète avant de commencer revient à repousser le travail réel à un horizon qui n’arrive pas. J’ai vu une équipe partir là-dedans : trois semaines de tests écrits, dont la moitié sur des modules que personne ne comptait rouvrir. Découragement, et le bug d’origine toujours en place. La couverture n’est pas l’objectif. Ce qu’on cherche, c’est pouvoir modifier sans trembler.
D’où l’outil central de la reprise : le test de caractérisation. Il déroute la première fois, parce qu’il ne vérifie pas que le code est correct. Il enregistre ce que le code fait. On exécute, on lit la sortie réelle, on la grave comme référence. Même si elle paraît bizarre, même si elle est discutable.
Pourquoi figer un comportement bancal ? Parce qu’en production, il est devenu une dépendance. Des modules en aval s’appuient dessus, des utilisateurs ont bâti leurs habitudes autour, défauts compris. Le test vous évite de casser tout ça par accident. Le jour où vous voudrez vraiment changer ce comportement, ce sera un choix assumé, et vous mettrez le test à jour en sachant pourquoi.
Où poser les premiers tests
Je ne caractérise pas au hasard. Je vise les endroits qui paient tout de suite.
- Autour de la zone que je vais toucher. Avant de modifier une fonction, je grave ce qu’elle produit aujourd’hui, je modifie, puis je contrôle que seul le changement voulu a bougé.
- Sur les chemins critiques, ceux dont une régression silencieuse coûte cher : une facturation, un calcul de droits, un export comptable. Exactement le scénario qui m’avait piégé plus haut.
- Le reste suit, au fil des modifications, sans campagne héroïque.
Dès que ces premiers tests sont en place, modifier le code n’a plus le même goût. Avant, vous espériez ne rien casser et vous livriez le ventre noué. Maintenant, un filet vous prévient à la première dérive, et la peur de toucher au système (celle qui gèle des projets entiers pendant des mois) recule. Vous reprenez la main.
Concrètement, par où démarrer demain matin ? Prenez le prochain ticket qu’on vous confie, et ne couvrez rien d’autre que les quelques fonctions que ce ticket vous oblige à traverser. Un test, une zone, une modification. Pas de grand plan de couverture affiché en réunion : juste assez de filet pour ce que vous changez aujourd’hui, et vous recommencez au ticket suivant. C’est lent, mais ça avance sur du vrai legacy, là où les grandes campagnes échouent.