Tous les articles et vidéos

Figez le comportement avant d'y toucher

Avant toute migration, laissez l'agent écrire les tests qui manquent au code legacy. Migrez, puis relancez-les. Chaque rouge est une décision, pas une surprise.

Adil Ben Moussa
07 novembre 2026· 5 min
Figez le comportement avant d'y toucher

La partie précédente a renvoyé le plan de l'agent qui commence par « supprimer », et l'a remplacé par trois fichiers de tâche. Cette partie traite du premier, la tâche 000, qui passe avant tout nouveau code. Même un bon plan est tenté de commencer par la nouvelle fonctionnalité. Le bon point de départ, c'est le code tel qu'il est aujourd'hui.

Une photographie, pas un jugement

Avant toute étape de migration, écrivez les tests que le code n'a jamais eus. Pas pour le nouveau code, pour l'ancien, en l'état.

Commencez par le plus simple : les parties pures. Une méthode de validation, une fonction de formatage, un service qui convertit une réponse en modèle de vue. Dans le dépôt de démonstration, le composant de virement legacy contient une méthode validate() : sept règles en une douzaine de lignes, à figer en moins d'une demi-heure. L'agent excelle à cet exercice, plus qu'à n'importe quelle autre étape d'une migration, à une condition inscrite dans le fichier de tâche : il n'a pas le droit de modifier le code testé. Il lit validate(), écrit un fichier avec un cas par règle, y compris la règle erronée, et s'arrête là.

Ces tests consignent ce que fait l'ancien code, bugs compris. C'est tout l'intérêt.

Ils ne jugent pas le code. Ils le photographient.

Migrer, puis comparer

Appliquez maintenant le plan de la partie précédente : construire la nouvelle fonctionnalité à côté de l'ancienne, puis basculer la route. Lancez ensuite les mêmes cas sur le nouveau code.

Chaque vert est un comportement préservé sans que personne ait eu à s'en souvenir. Chaque rouge est une décision prise en connaissance de cause : soit un bug que vous choisissez désormais de corriger, dans son propre , avec un test mis à jour qui le dit, soit une régression repérée avant qu'un client ne la découvre.

Écrire des tests pour du code que vous allez supprimer ressemble à du temps perdu. Ce n'en est pas : ces tests sont la seule trace de ce que l'ancien code faisait vraiment, et c'est à leur aune que se mesure la migration. Avec un agent, cette trace coûte peu à écrire, et la règle ne change pas : figer d'abord, migrer ensuite, comparer enfin.

Le fichier de tâche de l'étape zéro

Version condensée de docs/tasks/000-pin-legacy-transfers.md, dans le dépôt de démonstration :

# Tâche 000 : figer le comportement de libs/legacy/transfers avant toute migration
 
## Périmètre
- Autorisé à modifier : rien de ce qui existe
- Nouveaux fichiers autorisés dans : libs/legacy/transfers/src/lib/*.spec.ts
 
## Hors périmètre
- Tout fichier qui n'est pas un spec. Si validate() semble fausse, écrire le test qui prouve ce qu'elle fait aujourd'hui et ajouter `// TODO 000: semble faux parce que …` au-dessus du test, pas dans le code
 
## Terminé quand
- [ ] Un it() par branche de TransferComponent.validate(), nommé d'après le comportement qu'il consigne
- [ ] Un it() par méthode publique de TransferService, via le vrai AccountsStore et un FakeBackend instantané
- [ ] Chaque assertion vérifie une chaîne ou un nombre écrit en dur, jamais une valeur recalculée par le code testé
- [ ] npm run test passe
- [ ] git diff --stat main -- ':!*.spec.ts' n'affiche rien (aucun changement hors des fichiers spec)
- [ ] Diff ≤ 300 lignes

La ligne sur les valeurs en dur compte plus qu'il n'y paraît. Un agent écrira sans hésiter expect(error).toBe(blockerMessage['insufficient-funds']) : la valeur attendue est lue dans le code au lieu d'être écrite noir sur blanc, si bien que le test donne raison au code quoi qu'il dise. Un 'This account is closed.' écrit en dur est une photographie. Une valeur recalculée est un miroir.

Prompt · figer le code legacy

Lis AGENTS.md et docs/tasks/000-pin-legacy-transfers.md. Écris des tests de caractérisation pour validate() dans libs/legacy/transfers/src/lib/transfer.component.ts et pour TransferService.

Règles : ne modifie aucun fichier autre qu'un nouveau *.spec.ts. Un it() par règle ou par branche, nommé d'après le comportement qu'il consigne. Vérifie des chaînes et des nombres écrits en dur. Là où le comportement actuel ressemble à un bug, garde le test fidèle à ce comportement et ajoute // TODO 000: semble faux parce que … au-dessus. Lance npm run test et indique le nombre de tests.

Lisez les qu'il laisse. Ils forment la liste des bugs de votre module legacy, dressée par un outil qui a lu chaque branche.

Figez aussi l'écran

Les tests unitaires figent les règles. Ils ne figent pas l'écran, or c'est justement l'écran que vous vous apprêtez à réécrire. Ajoutez donc, pour chaque flux critique, un test qui ouvre une URL et non un composant. Le RouterTestingHarness d' le permet dans la même exécution de tests, sans navigateur :

const harness = await RouterTestingHarness.create('/transfers/new/a-current');

Remplissez les champs par leur libellé, lisez le message affiché à l'écran, jamais une classe ni un nom de composant. Le test ne connaît que la route : il affiche donc ce vers quoi elle pointe, l'ancien composant aujourd'hui, le nouveau après la bascule. Dans le dépôt de démonstration, le même spec tourne avant et après la bascule. C'est le critère « terminé quand » de l'écran modernisé. Si votre équipe dispose déjà de tests , ils font le même travail.

Ce que ce n'est pas

Ce n'est pas une couverture complète. Figez ce qui coûte peu et ce qui fait peur : les règles, l'argent, les dates, tout ce qu'un client remarquerait. Les détails de ne méritent pas de tests unitaires ; le test par URL couvre l'essentiel. Un après-midi, pas un .

Dès lundi

  • Choisissez un module legacy. Demandez à l'agent de lister ses fonctions pures. Figez-les en premier.
  • Avant de toucher à un template, écrivez un test qui ouvre son URL et déroule le flux principal.
  • Inscrivez « aucun changement hors de *.spec.ts » dans le « terminé quand », et vérifiez-le avec git diff --stat.
  • Gardez les mêmes tests actifs sur le nouveau code jusqu'à la suppression de l'ancien.

Exercice : module 2, scène 0 dans le dépôt de démonstration. Départ : git switch -c m2/you main. Référence : les deux specs legacy dans libs/legacy/transfers/src/lib/ sur origin/track1/m2-ngmodule-solution~1, l'état juste avant la suppression.

Tout cela s'appuie sur le compilateur et sur un exécuteur de tests qui voit chaque template. La partie suivante traite du legacy où ce n'est plus vrai : au sein d'une application Angular.


Parcours 1, partie 5 de la série gratuite qui accompagne le Vite et sûr : l'IA dans votre code Angular.

Partager cet article
Workshop

Vite et sûr : l'IA dans votre code Angular

Laissez des agents écrire de l'Angular sous règles, modernisez le code legacy sans casser la production, et gardez le tout sécurisé, en trois jours, sur un code à l'échelle d'une entreprise.

Voir le programme
À lire ensuite
Panneaux InDesignLe produitPanneaux InDesignMigration d'AngularJS vers Angular · Angular | AngularJS | Adobe InDesignLe projet