Recherche/Améliorer un outil de test par mutation à partir du code et des tests actuels

Améliorer un outil de test par mutation à partir du code et des tests actuels

Pour modifier un outil de test par mutation. Vérifie d’abord le code et les tests actuels, garde l’ordre de traitement et l’évaluation différée, ajoute des mutateurs sans mutants invalides, écrit des tests qui les détectent et suit des étapes sûres de revue, CI et publication.

Pour utiliser ces règles d'IA
## Vérifier le code, les tests et les notes de conception actuels avant chaque changement Considérez l’arborescence actuelle des sources, les tests, les schémas, les décisions d’architecture et la documentation destinée aux contributeurs comme la spécification. Ne vous fiez ni à votre mémoire, ni à d’anciennes hypothèses, ni à un modèle générique de framework lorsque les preuves du dépôt les contredisent. Pour chaque fonctionnalité ou correction : 1. Recherchez les tests unitaires, d’intégration, de bout en bout, d’architecture et d’auto-mutation les plus proches, y compris les noms apparentés, les échecs, les entrées non valides et les cas limites. 2. Lisez l’implémentation responsable afin de comprendre l’ordre, les valeurs par défaut, la sémantique des échecs et les contraintes de performance. 3. Lisez les décisions de conception référencées et les discussions en amont lorsque l’intention n’apparaît pas clairement dans le code. 4. Écrivez ou adaptez avant l’implémentation un cas ciblé qui échoue, puis reliez-le aux preuves correspondantes. 5. Consignez la raison des mécanismes non évidents, des seuils de version et des incompatibilités délibérées. Employez systématiquement le glossaire du projet. Modélisez une mutation comme une description sérialisable susceptible d’être appliquée dans un autre processus, et un mutateur comme une vérification d’éligibilité distincte suivie d’une transformation. Cartographiez la chaîne d’exécution avant de la modifier : la configuration, la collecte des sources et de la couverture, l’enrichissement de l’AST, la génération des mutations, l’exécution des mutants, l’analyse complémentaire facultative et la production des rapports constituent des frontières ordonnées de responsabilité. Si un changement invalide un chemin, un contrôle ou une convention documentés, mettez à jour cette documentation dans le même changement. ## Respecter les règles de l’API publique, des types et du nommage - Le code de production ne doit pas dépendre des tests ni des mesures de performance. Placez les utilitaires de test distribués dans un espace de noms de test explicitement rattaché à la production et imposez mécaniquement le sens de la dépendance. - Traitez l’API publique comme une liste d’autorisation. Marquez tout le reste comme interne, documentez les points d’extension et classez toute modification de cette liste comme un événement de compatibilité. - N’utilisez strictement `final` que pour les classes qui ne seront jamais remplacées par des doublures de test. Gardez les services simulables techniquement redéfinissables sans ajouter une interface dans le seul but de simuler une classe. - Importez les fonctions et les constantes de façon cohérente. Pour les appels susceptibles de renvoyer `false`, choisissez une sémantique d’échec explicite : utilisez une enveloppe sûre quand l’échec est exceptionnel et un alias non sûr clairement nommé lorsque le retour false est nécessaire. - Préférez les constantes typées, les marqueurs explicites de redéfinition et les objets-valeurs immuables. Ne rendez pas une classe `readonly` si elle mémorise des résultats dans ses propres propriétés. - N’employez les assertions à l’exécution que pour les invariants que l’analyse statique ne peut pas prouver. Leur message doit désigner l’anomalie qu’un échec révélerait. - Faites exprimer les contrats par les noms : `find*` renvoie une valeur nullable, `get*` garantit une valeur, les constructeurs nommés expriment le sens métier et les exceptions décrivent l’échec métier au lieu de se terminer génériquement par `Exception`. - Réservez `Memoized*` à une réutilisation invisible, une fois par instance. N’utilisez `Cached*` que si les appelants peuvent observer les clés, l’invalidation, la durée de vie TTL ou un stockage partagé. - Rendez non instanciables les classes purement statiques ou ne contenant que des constantes. Réservez l’injection de dépendances aux composants avec état ou réalisant des E/S. - Gardez identifiable le code repris en amont, conservez son attribution et documentez chaque divergence locale intentionnelle. ## Préserver l’évaluation différée et passer les commandes de sous-processus en tableaux d’arguments - Représentez les valeurs réutilisables coûteuses par une abstraction différée avec mémoïsation. Un générateur brut ne se parcourt qu’une fois et ne doit être ni rembobiné, ni compté, ni mis en mémoire tampon. - Distinguez le mappage strict d’un à un du mappage à plat d’un à plusieurs. Des noms de méthodes similaires ne doivent pas masquer des cardinalités de flux différentes. - N’autorisez une mutation par référence dans un chemin critique mesuré que si sa propriété et son effet sur place sont documentés. - Injectez des abstractions d’horloge et de système de fichiers au lieu d’appeler directement les primitives de temps ou de disque. Les tests doivent pouvoir contrôler les résultats temporels et ceux du système de fichiers. - Représentez de bout en bout les commandes de sous-processus par des tableaux d’arguments textuels. Un élément du tableau correspond exactement à un argument ; ne préassemblez jamais une commande d’interpréteur et ne supposez pas qu’elle sera découpée sur les espaces. - Maintenez un seul registre de services explicite, avec des accesseurs typés et des fabriques initialisées à la demande. Les consommateurs ne doivent pas effectuer de recherche de service non typée, et les services spéculatifs inaccessibles sont interdits. - Reliez de nouveau la configuration en clonant le conteneur plutôt qu’en modifiant l’état partagé du processus. Extrayez un assembleur typé lorsqu’une fonction de câblage devient complexe. - Fusionnez la configuration selon la sémantique de chaque champ : les redéfinitions nullables utilisent la coalescence nulle, tandis que les indicateurs que l’une ou l’autre source peut imposer utilisent un OU logique. Unifier ces règles modifie silencieusement le comportement. - Résolvez les chemins de sortie relatifs à partir de l’emplacement du fichier de configuration, préservez les chemins de flux explicitement autorisés et calculez une base de contrôle de version afin de ne traiter que les changements voulus par l’utilisateur. ## Respecter l’ordre de traitement de l’AST sans modifier l’arbre d’origine - Considérez l’ordre d’enregistrement des visiteurs comme une partie de l’algorithme. Résolvez les noms et les parents avant leurs consommateurs, appliquez les exclusions avant de rattacher les tests et réinitialisez l’état réutilisable des visiteurs avant chaque fichier. - Communiquez au moyen d’accesseurs typés aux attributs des nœuds. Une exclusion marque un nœud comme inéligible ; elle ne supprime ni ne remplace jamais de nœud pendant l’enrichissement. - Rattachez les recherches de couverture coûteuses de manière différée et uniquement aux nœuds éligibles. Préservez les deux niveaux d’évaluation différée entre la découverte des fichiers de couverture et l’analyse, fichier par fichier, des emplacements de test. - Faites passer les requêtes XML par une enveloppe sûre tenant compte des espaces de noms. Conservez les solutions de repli ordonnées entre formats ainsi que leur justification de version ; un nettoyage ne doit pas supprimer une branche encore prise en charge. - Maintenez l’exécuteur de processus en flux continu. Les identifiants de processus de travail consommés par les tests des utilisateurs sont des valeurs exactes de l’API, indexées à partir de 1. L’analyse complémentaire appartient à la chaîne de conteneurs de processus, pas à des branches propres à l’ordonnanceur. - Préservez la sémantique des unités dans les calculs d’ordonnancement : le temps passé à mettre du travail en file est une durée, non un nombre d’éléments. Libérez les références aux conteneurs terminés avant de réutiliser les emplacements des processus de travail. - Gardez séparées et composables les modifications de configuration de l’exécuteur de tests propres à chaque version. Préservez la configuration moderne de couverture faisant autorité, les filtres d’inclusion de l’utilisateur, les chemins acceptant les motifs glob et les anciennes formes de document. - Faites correspondre une cible de mutation à partir des positions des jetons et de la classe du nœud. Clonez l’AST d’origine avant la mutation, préservez les jetons originaux pour une impression conservant la mise en forme et gardez l’arbre d’origine identique octet pour octet. - Considérez les empreintes de mutation, l’ordre des champs et les attributs de position obligatoires comme des contrats publics de réexécution. Copiez chaque enfant et chaque attribut lors de la reconstruction des nœuds ; un remplacement valide peut être une valeur scalaire, un nœud ou une liste de nœuds. ## Créer des mutateurs qui ne produisent ni mutants invalides ni mutants équivalents Une modification complète d’un mutateur met à jour l’implémentation, chaque registre central et chaque table de correspondance des profils, le schéma de configuration, un test canonique et la documentation utilisateur lorsque le comportement est public. - Réduisez au minimum la surface publique du mutateur : définition, nom stable, éligibilité et transformation, avec un accès à la configuration uniquement si le mutateur est configurable. - La définition doit expliquer la mutation, sa catégorie, un exemple comparatif du changement et la manière dont un utilisateur peut éliminer le mutant. - Dans les vérifications d’éligibilité, comparez les identifiants du langage selon leurs véritables règles de casse et remontez les nœuds ancêtres lorsque le contexte imbriqué importe. - Ne générez jamais d’erreurs de syntaxe, d’erreurs fatales garanties, de mutations équivalentes, de boucles infinies ni de mutation déjà prise en charge par un autre mutateur. - Lorsqu’un chevauchement ou une équivalence est possible, exposez le raisonnement et ajoutez un cas nommé de non-mutation. - Copiez tous les enfants et les métadonnées lors de la construction d’un nœud de remplacement de l’AST afin qu’aucun attribut ne soit supprimé silencieusement. - Exercez les mutateurs au moyen de l’infrastructure de parcours utilisée en production. Ne construisez pas de parcours ponctuel qui contourne le comportement d’éligibilité ou de portée. - Considérez l’absence de sortie attendue comme une assertion explicite de non-mutation et formulez les noms des jeux de données comme des spécifications. - Lorsque le volume de mutations change, indiquez pour chaque mutateur le nombre de mutants générés, éliminés, survivants et arrivés au délai d’expiration. ## Écrire des tests reproductibles qui détectent les mutants - Attribuez à chaque classe source concrète un test canonique et à chaque test une cible de couverture explicite. - Classez les tests avec E/S comme tests d’intégration et ceux sans E/S comme tests hors intégration. Imposez cette frontière dans les deux sens. - Gardez les tests déterministes : utilisez des chemins temporaires générés, fixez le degré de concurrence pour les données de test sensibles à l’ordre de sortie, sauvegardez les variables d’environnement et évitez les chemins inexistants inscrits en dur. - Utilisez des fournisseurs de données statiques avec des noms de cas descriptifs. Préférez les arguments nommés et les valeurs par défaut pour les signatures de test étendues, mais ne partagez pas un fournisseur entre des tests qui consomment des sous-ensembles différents. - Remplacez les graphes profonds de doublures simulées par de petits assembleurs immuables ou des objets factices. Faites vérifier des arguments exacts par les attentes sur les doublures afin que les mutations ne puissent pas échapper à des assertions trop souples. - Structurez le code de production pour rendre les mutations visibles : préférez les retours anticipés, les résultats booléens séparés et les constantes nommées aux littéraux magiques impossibles à tester. - Évitez les arguments par défaut des constructeurs qui masquent des dépendances manquantes. Les valeurs par défaut des fournisseurs de données sont acceptables lorsqu’elles permettent à chaque cas de n’indiquer que sa variation. - Utilisez les infrastructures de test des visiteurs et des commandes ainsi que les autres préparations du projet alignées sur la production. N’écrivez pas un script de sondage jetable lorsqu’un test unitaire ciblé devrait exister. - Un mutant survivant indique soit un test manquant, soit un code qui doit être remanié. Discutez les cas véritablement impossibles à éliminer ou exclusivement liés aux performances au lieu d’écrire un test artificiel. - Pendant l’itération, exécutez des tests ciblés. Avant la transmission, exécutez l’outil de mise en forme du dépôt, la revue d’architecture et d’analyse statique, les groupes d’intégration pertinents et la suite complète faisant autorité. ## Garder les réglages par version et les solutions de repli lors du nettoyage du code - Conservez les seuils de version et les enchaînements de repli documentés avec le comportement qu’ils protègent. Ne simplifiez pas une matrice de compatibilité sous prétexte que seule sa forme la plus récente est familière. - Dans les minilangages de configuration ordonnés, traitez les clés dans l’ordre et laissez les entrées ultérieures l’emporter. Une sentinelle `false` doit retirer tout ce que cette clé a enregistré, y compris les profils imbriqués. - Préservez le sens de fusion et la déduplication explicite lors de la combinaison des réglages. Une sélection en ligne de commande peut remplacer la sélection du fichier tout en conservant les règles globales d’exclusion. - Faites d’un registre unique la source faisant autorité pour l’ensemble des mutateurs pris en charge et dérivez-en les contrôles automatisés de couverture. - Lorsqu’un filtre de noms de tests approche la limite des expressions régulières, passez d’un filtrage précis à un sur-ensemble sûr, puis omettez finalement le filtre afin d’exécuter toute la suite. Ne revenez jamais à une exécution sans aucun test. - Préservez la règle associée selon laquelle le résultat « aucun test exécuté » d’un exécuteur est une réussite lorsqu’une sélection vide est valide. - Après un redémarrage sans débogueur, ne déduisez pas les capacités de l’extension actuellement chargée. Demandez au gestionnaire du redémarrage quelle version a été ignorée et n’activez la couverture que dans le processus enfant qui en a besoin. - N’appliquez les ajustements de limite de mémoire qu’à la configuration temporaire du processus enfant, après l’analyse statique, et effectuez-les au mieux avec des garde-fous explicites. - Mesurez les optimisations gourmandes en processus avant de les conserver. Réévaluez les anciens contournements de performance lorsque les versions de l’environnement d’exécution ou de la chaîne d’outils changent. ## Protéger le fichier de verrouillage et ne fusionner que des pull requests dont la CI passe Ne contournez jamais un fichier de verrouillage figé pendant une installation sans surveillance. Si la résolution des dépendances exige de modifier ce fichier, arrêtez-vous et obtenez une autorisation explicite. Les versions exactes, les empreintes d’intégrité et la compatibilité des licences constituent des frontières de la chaîne d’approvisionnement. Ne poussez jamais directement vers une branche principale protégée, ne contournez pas sa protection et ne forcez pas une fusion administrative. Suivez cette séquence : 1. Créez une branche dédiée à la fonctionnalité. 2. Effectuez le plus petit changement cohérent et lancez les contrôles ciblés. 3. Créez le commit selon la convention de messages exigée par le dépôt. 4. Poussez la branche et ouvrez une demande d’intégration. 5. Attendez tous les contrôles obligatoires de formatage, de types et de tests unitaires, d’intégration et de bout en bout. 6. Corrigez les échecs au lieu de les contourner. 7. Fusionnez selon la méthode approuvée et supprimez la branche. Ne mélangez pas les remaniements aux changements de comportement. Les anomalies corrigées exigent des tests de régression, les ruptures de compatibilité des notes de publication et des instructions de migration explicites, et le comportement visible par l’utilisateur une documentation utilisateur synchronisée. Laissez l’automatisation de publication dériver les métadonnées des messages de commit conventionnels. N’utilisez les dérogations documentées que pour des reclassements délibérés et ne modifiez jamais à la main les artefacts de publication générés. Exécutez l’intégration continue des contributions non fiables sans secrets et avec des droits de lecture seule. Les aperçus nécessitant des secrets doivent ignorer les dépôts dérivés, sauf si un responsable autorisé les déclenche explicitement au moyen d’une commande soumise à un contrôle d’identité. Enregistrez chaque exemple déployé dans la matrice de construction et ajoutez un test élémentaire de fonctionnement pour son chemin, son état et son contenu. Une publication ou un déploiement n’est achevé qu’après la réussite des contrôles obligatoires et des preuves postérieures au déploiement.