Les enregistrements d’identité dans les fixtures de test sont les lignes qu’une suite de tests conserve en permanence : la personne qui a l’âge requis, celle qui ne l’a pas, le client dont l’adresse est une seule chaîne ininterrompue, le compte sans nom de famille. Ils sont peu coûteux à créer et faciles à mal garder, et un ensemble de fixtures qui se désynchronise du produit est pire que pas de fixtures du tout, car il inspire une fausse confiance.
Ce guide couvre la manière d’organiser les enregistrements d’identité au sein d’un ensemble de fixtures, quels cas limites méritent d’être conservés, et comment empêcher la collection de pourrir discrètement.
Qu’est-ce qui appartient à une fixture plutôt qu’à un générateur ?
Une fixture s’utilise quand le test affirme un résultat précis, et un générateur s’utilise quand le test traque des problèmes d’entrée inconnus. La distinction ne porte pas sur la taille ni sur le formalisme ; elle porte sur la question de savoir si quelqu’un a besoin de connaître l’entrée à l’avance.
Cela signifie que les fixtures servent au comportement : étant donné cette personne, le système doit prendre cette branche. Les générateurs servent à l’exploration : alimentez le système avec beaucoup de personnes plausibles et regardez ce qui casse. Un test qui affirme une réponse mais tire son entrée au hasard ne teste pas le comportement qu’il prétend tester, car l’exécution suivante peut exercer une autre branche et cesser de couvrir le cas que l’auteur avait en tête.
La plupart des suites ont besoin des deux, et la convention utile est de rendre la distinction visible. Les fixtures vivent dans des fichiers aux valeurs stables et aux noms lisibles. Les enregistrements générés vivent dans une étape qui s’exécute au moment du test. Mélanger les deux dans un même fichier est la manière dont une suite devient impossible à raisonner six mois plus tard.
Pourquoi « aléatoire à chaque fois » rend-il les défaillances irreproductibles ?
Parce que le rapport de défaillance ne contient aucune entrée. Un test qui tire un nouvel enregistrement à chaque exécution produit une pile d’appels, une capture d’écran et rien d’autre ; l’exécution suivante peut réussir, et l’ingénieur reste à deviner si le correctif a fonctionné ou si les dés ont changé.
C’est la source la plus courante de tests instables dans les systèmes riches en données, et les dégâts s’accumulent. Les ingénieurs apprennent à relancer les tests en échec jusqu’à ce qu’ils passent au vert, ce qui habitue lentement toute l’équipe à ignorer le signal que la suite existe pour fournir. La reproductibilité n’est pas un agrément ici ; c’est la propriété qui donne un sens au reste de la suite.
Le correctif consiste à figer l’entrée et à laisser la variation venir d’un endroit contrôlé. Lorsqu’un enregistrement est généré plutôt qu’écrit à la main, le dériver d’une clé fixe donne la même personne à chaque exécution, si bien qu’une assertion reste stable et qu’un rapport de bug peut nommer l’enregistrement exact qu’il a vu.
Comment les enregistrements de fixtures doivent-ils être nommés et regroupés ?
Nommez chaque enregistrement d’après la situation qu’il existe pour tester, et non d’après les valeurs qu’il contient. Un enregistrement appelé par exemple « candidat de plus de dix-huit ans » dit au lecteur suivant à quoi il sert ; un enregistrement nommé d’après un nom de famille ne lui dit rien et sera réutilisé à mauvais escient dans le mois.
Le regroupement suit la même logique. Un fichier de fixture par fonctionnalité ou par scénario, contenant uniquement les personnes dont ce scénario a besoin, garde le fichier lisible et rend évident le moment où un enregistrement est devenu inutilisé. Un seul fichier énorme de cent enregistrements est le schéma qui produit des suites où personne ne peut dire quelle fixture compte encore, si bien que personne n’ose en supprimer aucune.
Deux pratiques plus modestes se rentabilisent. Placez un commentaire en tête de chaque groupe de fixtures indiquant à quoi sert le groupe et quand il a été revu pour la dernière fois. Et gardez les valeurs dans la fixture, pas dans le code de test, afin que changer un enregistrement n’exige pas de modifier les assertions.
Quels cas limites d’identité méritent une fixture permanente ?
Une courte liste couvre une quantité surprenante de risque, car chaque entrée casse une hypothèse différente plutôt qu’une valeur différente.
| Fixture | L’hypothèse qu’elle casse |
|---|---|
| Une personne de plus d’un siècle | Que les années de naissance sont toujours dans une plage étroite |
| Un nom bien plus long que l’interface ne le permet | Qu’une largeur de champ d’exemple est représentative |
| Une personne sans nom de famille | Qu’il existe toujours deux parties de nom |
| Un nom dans une écriture non latine ou avec des diacritiques | Que l’alphabet est toujours le latin |
| Un enregistrement avec un identifiant facultatif absent | Que chaque champ est toujours renseigné |
| Une date de naissance un jour bissextile | Que chaque date se produit chaque année |
| Un enregistrement avec une paire délibérément incohérente | Que les règles de cohérence sont encore appliquées |
La dernière entrée est celle que les équipes omettent le plus souvent, et c’est la plus précieuse. C’est la seule fixture qui échoue lorsqu’une règle de cohérence est accidentellement désactivée, et les règles de cohérence sont exactement le type de code que l’on assouplit pendant un incident et que l’on ne resserre jamais.
Comment les fixtures pourrissent-elles, et qu’est-ce qui l’arrête ?
Une fixture ne devient pas fausse toute seule ; le système autour d’elle change. Un seuil passe d’un âge à un autre et la personne qui avait tout juste l’âge ne l’a plus. Une règle de validation se resserre et un enregistrement qui passait échoue désormais, ce qui fait passer au rouge un test réussi pour une raison sans rapport avec le code testé. Un changement de format global arrive et la moitié du fichier de fixtures devient obsolète sans que personne ne le remarque.
Trois habitudes ralentissent cela. Les fixtures dépendantes de la date devraient indiquer la date qu’elles supposent, afin que le passage du temps soit visible dans le fichier plutôt que découvert dans une compilation rouge. Les fixtures devraient être exercées régulièrement plutôt que seulement lorsque leur fonctionnalité change, afin que la casse apparaisse tôt au lieu de surgir lors d’un changement sans rapport. Et les revues devraient demander si chaque enregistrement mérite encore sa place, car le coût d’une fixture n’est pas sa création mais la confusion qu’elle cause une fois sa raison oubliée.
Le point plus profond est que les fixtures sont des données dotées d’un contrat de maintenance, et une suite qui les traite comme une histoire immuable finira par tester le produit tel qu’il était, et non tel qu’il est.
Les fixtures doivent-elles être générées, tout court ?
En partie, et le partage mérite d’être délibéré. Les enregistrements qui existent pour figer un comportement devraient être écrits, car quelqu’un a besoin de les inspecter et de raisonner à leur sujet. Les enregistrements qui existent pour fournir du volume — une centaine de lignes pour un test d’import, un millier pour une répétition de migration — gagnent à être dérivés, car personne ne peut lire une centaine de lignes et leurs valeurs exactes n’importent pas tant que la forme est bonne.
La raison de dériver le volume plutôt que de le versionner est la reproductibilité à l’échelle. Un fichier versionné de mille lignes est une charge de maintenance qui grandit à chaque changement de schéma, tandis qu’un lot dérivé peut être reconstruit dès que le schéma bouge, et reconstruit à l’identique s’il est piloté par une clé fixe. Les enregistrements tirés du générateur d’identités et de données de test fonctionnent dans ce rôle : cohérents en interne par pays, reproductibles à partir d’une clé, et clairement synthétiques afin que personne ne confonde une ligne avec un vrai client.
Pour le petit ensemble écrit à la main, l’inverse s’applique. Gardez-le minuscule, gardez-le lisible, et gardez chaque enregistrement lié à un scénario nommé afin que supprimer l’un soit une décision éclairée plutôt qu’une supposition. Tout, dans les deux moitiés de l’ensemble, est inventé pour les tests logiciels ; rien ne décrit une personne réelle, et rien ne peut servir d’identité à quiconque.
Pour les développeurs : structurer l’ensemble de fixtures
Traitez les données de fixture comme une partie du code de test et appliquez les mêmes normes. Chaque enregistrement a besoin d’un nom qui énonce son scénario, d’un court commentaire expliquant pourquoi il existe, et d’une place dans un groupe assez petit pour être lu d’un seul coup d’œil. Les valeurs vivent dans des fichiers de données plutôt que dans les assertions, afin qu’un enregistrement puisse être mis à jour en un seul endroit.
Faites ensuite démontrer ses propres entrées à la suite. Exécutez le contrôle de cohérence contre les fixtures elles-mêmes, et pas seulement contre les données entrantes, afin qu’une fixture qui se contredit échoue bruyamment au lieu de tester discrètement le chemin tolérant. Injectez la date courante plutôt que de la lire, afin qu’une fixture avec une date frontière ne change pas de sens du jour au lendemain. Et gardez un enregistrement délibérément cassé dans l’ensemble, avec l’assertion qu’il est rejeté, comme preuve permanente que les garde-fous sont encore activés.
Enfin, consignez la provenance. Une note d’une ligne indiquant que ces enregistrements sont synthétiques et générés pour les tests protège le lecteur suivant de supposer qu’ils proviennent d’une base de données quelque part, ce qui est exactement l’hypothèse qui mènera un jour à ajouter un vrai enregistrement au fichier parce qu’il était à portée de main.
Étapes suivantes
Ouvrez votre plus gros fichier de fixtures et essayez de supprimer les dix enregistrements aux noms les plus vagues ; tout ce que vous ne pouvez pas justifier est un enregistrement que personne ne comprend. Ajoutez ensuite l’enregistrement délibérément incohérent s’il manque, affirmez que le système le rejette, et confirmez que la suite passe au rouge quand ce contrôle est désactivé. Le guide sur la cohérence des champs explique les paires que cet enregistrement devrait casser, et un lot frais issu du générateur d’identités couvre la moitié « volume » de l’ensemble.