Repository navigation
FR Contribuer Tests De Mutation
English · Procédure + explication · Publiée, relue par une personne · S'applique depuis : 4.3.1
Des lignes exécutées par un test ne sont pas une preuve : les tests de mutation demandent si les tests distinguent un bon résultat d'un mauvais. Cette page dit comment quest'n'click s'y prend, et que faire quand un mutant survit à votre changement.
Public, contexte, et statuts de ce sur quoi repose la page
Public : contributeur · Contexte : dépôt du moteur
Un ensemble de mutation qui repasse après votre changement : chaque mutant de ses fichiers est tué par un test, ou nommé
dans docs/dev/mutants.json avec une catégorie, une raison, une preuve, un responsable et une version de relecture.
Chaque mutant change une seule chose dans un fichier source : un opérateur de comparaison ou logique échangé (< pour
<=, && pour ||), une négation retirée, une condition forcée à true ou false, un booléen inversé. Les tests qui
jugent l'ensemble de ce fichier tournent contre lui, et l'un d'eux doit échouer. Un mutant qui survit est un test qui
manque, ou un mutant équivalent qu'aucune entrée ne distingue de l'original.
L'outil est tools/mutate.ts, écrit pour le projet en 4.1.0 « Clarity » : Stryker 10
n'activait pas ses mutants sous Vitest ici (739 sur 749 survivaient, un bloc vidé compris), alors chaque mutant tourne
en source ordinaire. Le fichier est restauré après chaque mutant, et à la sortie (Ctrl-C compris).
Un survivant non nommé fait échouer l'exécution, quel que soit le score. Il n'y a pas de seuil : un ensemble passe quand chaque survivant est expliqué, et une explication est une exemption avec ses conditions (plus bas), jamais « le score est assez bon ».
Le dépôt du moteur. L'outil depuis la 4.1.0, les ensembles et la barrière par identité depuis la 4.1.2, le découpage en morceaux et les conditions d'exemption depuis la 4.1.20 ; treize ensembles barrières en 4.4.0.
| Ensemble | Mute | Barrière depuis |
|---|---|---|
core |
src/engine/core/{cond,save,session-runtime,migrate}.ts |
4.1.2 |
reality |
la réception du moteur, le protocole, le client, le port HTTP ; le Bridge, son stockage de journal, son verrou et sa politique | 4.1.2 |
runs |
la file des speedruns : bridge/src/{runs,runs-store,runs-limiter}.ts
|
4.1.17 |
remix |
la graine d'un monde, sa compilation, son application, ses catégories ; les jetons Daily et Mystery | 4.1.17 |
speedrun |
l'enveloppe d'un run, l'enregistreur, le vérificateur | 4.1.17 |
connectors-pure (connectors jusqu'à la 4.2) |
les parties pures des connecteurs : SDK, lecteur MIME, éditeur de ligne, disque virtuel, cryptographie et récupération des badges | 4.1.18 |
reality-store |
les stockages du Bridge en mémoire, SQL et SQLite, migrations, flux, signature (pas l'adaptateur Postgres) | 4.1.18 |
connectors-edge |
configuration et démarrage, le connecteur e-mail, la vérification des badges, garde et shell du terminal, SSH, Telnet (4 morceaux) | 4.1.20 |
reality-store-postgres |
bridge/src/store-postgres.ts, jugé sur un vrai Postgres (BRIDGE_PG_URL) |
4.1.20 |
studio-ops |
le journal du Studio Server, ses écritures durables et les pans des fichiers d'un jeu | 4.2.1 |
studio-auth |
la barrière du Studio Server, le fournisseur OpenID, les routes et le stockage d'authentification, les baux des pans, l'origine du jeu | 4.2.1 |
studio-workshop |
l'annulation personnelle, la santé par révision, les aperçus, les builds, les assets préparés, la sauvegarde, le journal expédié et la collecte | 4.2.3 |
voices |
les voix par valeur : les clés des clips d'une réplique, la table d'enregistrement et son CSV, la vérification du validateur ; les phrases du solveur | 4.3.1 |
Les ensembles et les fichiers de test qui jugent chacun sont dans tools/mutation-sets.ts
(SETS, TESTS, GATED) ; MEASURED (les ensembles qui rapportent sans barrière) est vide depuis la 4.2.1. Où
chacun tourne, c'est Quels tests tournent quand : une pull request étiquetée
full-ci, chaque nuit (de zéro), le candidat et la release.
- Un dépôt préparé (Préparer son poste de développement), et les tests de l'ensemble verts avant
toute mutation : l'outil refuse de démarrer sinon (
✖ the tests fail before any mutation: fix them first). - Pour
reality-store-postgres: un Postgres que les tests peuvent utiliser, donné parBRIDGE_PG_URL(l'outil sort avec le code 2 sans lui, puisque chaque mutant survivrait à un test qui saute ses cas Postgres). - Du temps : un ensemble prend de quelques minutes à quelques heures ;
connectors-edgea pris 2 h 02 en un seul job sur un runner avant d'être coupé en quatre morceaux. En local, préférez--file, ou le workflowmutation.
Dans le dépôt du moteur, sur votre machine ; ou sur un runner avec le workflow mutation, qui mesure un ensemble sur
une référence et garde le rapport :
# depuis n'importe quel clone avec la CLI GitHub
gh workflow run mutation --ref main -f set=remix -f ref=<branche ou SHA> [-f file=<chemin>]L'outil réécrit le fichier source qu'il mute : ne le modifiez pas pendant une exécution.
-
Mutez le fichier que vous avez changé, jugé par les tests de son ensemble :
# dans le dépôt du moteur npm run test:mutation:core -- --file=src/engine/core/cond.tsIl affiche chaque mutant survivant sous la forme
survived <fichier>:<ligne> <opérateur>: <avant> → <après>, puis le score de chaque fichier, puis✖ not in docs/dev/mutants.json: …pour chaque survivant que personne n'a nommé.
-
Ou lancez l'ensemble entier, comme la CI :
# dans le dépôt du moteur npm run test:mutation:core -- --set=core # l'ensemble par défaut npm run test:mutation:reality # équivaut à --set=reality npm run test:mutation:core -- --set=all # chaque ensemble barrière, l'un après l'autre
Un rapport dont les entrées n'ont pas changé (
inputHash: les sources et les tests de l'ensemble, tout ce qu'ils importent, les deux configurations, l'outil, les survivants nommés, le fichier de verrouillage sans ses champs de version) est réutilisé : l'exécution le dit et s'arrête.--freshrelance quand même. Les rapports sont écrits dans.cache/mutation/report-<ensemble>.json.
-
Tuez le survivant avec un test, la réponse habituelle : écrivez l'entrée qui distingue le mutant de l'original,
dans un fichier de test que
TESTSliste déjà pour l'ensemble (ou ajoutez-y le fichier). Relancez l'étape 1 : le mutant est tué.
-
Ou nommez-le, quand aucune entrée ne peut le distinguer. Ajoutez une entrée à
docs/dev/mutants.json(en anglais, comme toute la documentation de développement) :{ "file": "src/engine/core/session-runtime.ts", "operator": "condition true", "from": "this.open.length", "to": "true", "context": "return this.open.length ? this.open[this.open.length - 1] : undefined;", "why": "`cur`: with no open entry, `this.open[-1]` is undefined, which is what the condition returned", "category": "equivalent", "proof": "argument", "owner": "@wanoo", "revisit": "4.6.0" }-
category:equivalent,unreachable,instrumentationouout-of-contract. -
why: plus de 20 caractères qui le disent. -
proof:argument(la raison est la preuve ; un mutant équivalent seulement), ou un fichier de test soustests/qui existe et fixe ce qui le rend tel. -
owner, etrevisit: la version à partir de laquelle l'entrée est refusée tant qu'elle n'a pas été relue. -
context: la ligne source sans ses espaces, pour que l'entrée ne nomme que le mutant de cette ligne.
Puis régénérez la table de
docs/dev/MUTANTS.mdet relancez l'ensemble :# dans le dépôt du moteur npm run test:mutation:core -- --doc npm run test:mutation:core -- --set=<ensemble> --fresh
docs/dev/mutants.jsonest un fichier que relit le mainteneur (CODEOWNERS) : dites dans la pull request pourquoi chaque entrée est équivalente. -
Limite ·
revisit-dueUne entrée dont la versionrevisitest atteinte arrête chaque ensemble, quel que soit son fichier : « docs/dev/mutants.json: n entries do not hold … to be read again at x.y.z ». En 4.4.0, les 132 entrées disent toutesrevisit: 4.5.0: dès quepackage.jsondit 4.5.0 (ses pré-versions comprises), chaque exécution de mutation refuse tant que chaque entrée n'a pas été relue et sonrevisitdéplacé.
✔ n/m mutants killed, k survivors explained, 0 not; report in .cache/mutation/…, et le code de sortie 0. Dans la CI,
les jobs mutation (<ensemble>) de l'ensemble et mutation-merge sont verts.
| Symptôme | Cause | Correction |
|---|---|---|
✖ not in docs/dev/mutants.json: <fichier>:<ligne> … |
Un survivant que personne n'a nommé | Tuez-le avec un test (étape 3), ou nommez-le (étape 4) |
⚠ named in docs/dev/mutants.json but killed or gone |
Une entrée dont le mutant ne survit plus | Retirez l'entrée |
✖ docs/dev/mutants.json: n entries do not hold |
Une entrée sans ses conditions, ou dont le revisit est passé |
Complétez-la, ou relisez-la et déplacez revisit
|
✖ --set=… mutates reality-store-postgres, which needs BRIDGE_PG_URL |
Aucun Postgres donné | Définissez BRIDGE_PG_URL, ou lancez un autre ensemble |
ℹ --set=connectors is --set=connectors-pure since 4.1.19 |
L'ancien nom | Utilisez le nouveau (l'alias marche jusqu'à la 4.2) |
✖ <ensemble>: … nothing merged, the set is not judged (CI) |
Un morceau manquant, en double, annulé ou d'autres entrées | Relancez les jobs de morceaux en échec, puis mutation-merge
|
L'outil réécrit le fichier source muté pendant qu'il tourne et le restaure après chaque mutant et à la sortie ; il écrit
ses rapports sous .cache/mutation/. Vous modifiez des fichiers de test, docs/dev/mutants.json et, par --doc,
docs/dev/MUTANTS.md.
Si une exécution a été tuée sans son gestionnaire de sortie (un kill -9, un plantage), regardez git status : un
fichier source muté apparaît modifié ; git restore <fichier> le remet en place.
-
docs/dev/MUTANTS.md, les survivants nommés expliqués ;docs/dev/mutants.json, la liste que lit la barrière. -
tools/mutate.ts,tools/mutation-sets.ts,tools/mutation-shards.ts,vitest.mutation.config.ts. - Le cliquet de couverture, La CI expliquée.
Generated publication · publication générée — current documentation · documentation courante: quest'n'click 4.5.4 r2, documentation revision · révision de la documentation 63112c877c587cc4fad16b25a3400408db2c36bd.
Latest documentation · dernière documentation: https://quest-n-click.cleverapps.io/docs · https://quest-n-click.cleverapps.io/fr/docs; earlier versions · versions précédentes: each release's quest-n-click-docs-<version>.tar.gz · l'archive quest-n-click-docs-<version>.tar.gz de chaque release, https://github.com/Quest-n-Click/quest-n-click/releases
An edit made in this wiki is overwritten at the next publication · une modification faite dans ce wiki est écrasée à la publication suivante.
Edit the source · Modifier la source · Report an error · Signaler une erreur
Index (6)
Démarrer (6)
Jouer (9)
Installer (18)
- Prérequis
- Installer depuis l'archive de la release
- Installer depuis npm
- Installer depuis le dépôt pour travailler sur le moteur
- doctor : vérifier sa machine
- Outils pour les images
- Outils audio : ffmpeg, fluidsynth, Furnace, uv
- Mettre à jour
- Notes de mise à jour : 4.5
- Notes de mise à jour : 4.4
- Notes de mise à jour : 4.3
- Notes de mise à jour : 4.2
- Notes de mise à jour : 4.1
- Notes de mise à jour : v3
- Notes de mise à jour : v2 vers v3
- Venir de web-scumm
- Référence du paquet
- Dépannage de l'installation
Créer un jeu (55)
- Votre premier jeu
- Organisation d'un projet créé et du dépôt du moteur
- La boucle de travail
- Principes du contenu et contrat d'identité
- Salles
- Géométrie : placement, zones de marche, masques, calques, caméra
- Un objet est visible mais inaccessible
- Réactions
- Commandes du jeu
- Conditions
- Drapeaux, variables et événements : lequel choisir
- Code sur mesure
- Personnages
- Objets et inventaire
- Carte du monde
- Dialogues
- Scripts et événements
- Faire bouger les personnages : patrouilles et marches
- Sorties
- Chapitres et objectifs
- État et sauvegardes : persistant ou temporaire, renommer un id, migrations
- Mise en scène : salles larges et animations
- La scène : lumières, particules, sols
- Habillage et polices
- Titre et générique
- Héros : plusieurs personnages et choix du héros
- Mini-jeux intégrés
- Un mini-jeu sur mesure
- Traductions
- Musique en stems
- Bruitages
- Voix : par langue et par héros
- Images : prompts, découpe des planches, transparence, échelle
- Provenance des assets
- Le storyboard, source de vérité
- Concevoir des énigmes
- Mécaniques classiques
- Pages de relecture
- Référence du DSL
- Vérifier son jeu
- Ce que prouve le solveur
- Options du solveur
- Playtests
- Remix
- Speedrun pour les auteurs
- La fin scellée
- Modèle de production
- Jeux d'exemple
- Travailler avec une IA
- Construire et publier un jeu
- Publier sur GitHub Pages
- Le jeu statique sur Clever Cloud
- Autres hébergeurs statiques
- Sous-chemin, cache et service worker, déploiement incomplet, retour arrière
- Tester sur un téléphone en réseau local
Studio local (24)
- Le Studio local : présentation et lancement
- Modifier une salle
- Placement et scène
- Aperçu, application, annulation
- Storyboard
- Assets et découpe
- Vérifier : validateur, solveur, chemin critique, chaleur, santé, couverture
- Captures avant et après
- Diff sémantique
- Jouer et rejouer une session
- Explication des règles
- Langue et objectifs
- Voix et matrice héros × langues
- Carte
- Notes
- Remix dans le Studio
- Musique
- L'Assistant : votre propre clé
- Mode démo et studio-apply
- Sécurité en local et en réseau local
- API du Studio
- MCP local : configurer chaque client
- Outils MCP
- Dépannage du Studio
Studio d'équipe (21)
- Ce qui tourne où
- Concepts : révision, transaction, pan, bail, aperçu, build
- Débuter comme dev invité
- Travailler ensemble au quotidien
- Rôles et actions : la matrice complète
- Invitations
- Gérer les membres
- Écriture refusée sur le Studio hébergé : révision de base périmée (409)
- Écriture refusée sur le Studio hébergé : pan verrouillé (423)
- Reprendre après un bail perdu, une déconnexion ou un aperçu périmé
- Commentaires
- Carte et diff sémantique
- Publier des builds
- MCP distant
- Le jeu dans Git
- Mettre à jour le moteur d'un jeu hébergé
- Assets hébergés
- La ligne de commande du serveur
- Routes de santé et de métriques
- L'essayer en local avec compose.yml
- Limites connues
Clever Cloud (23)
- Clever Cloud : vue d'ensemble, coût et prérequis
- Applications et add-ons
- Domaines et TLS
- Keycloak
- OIDC générique et GitLab
- Configuration
- Premier déploiement
- Sauvegardes
- RPO et RTO
- Exercice de restauration sur une installation vierge
- Redéploiements
- Mettre à jour le serveur et vérifier l'état après une migration
- Limites du retour arrière
- Supervision
- Sécurité
- Renouveler les clés
- Récupérer l'accès administrateur
- Changer de domaine ou de fournisseur OIDC
- Worker, PostgreSQL ou Cellar en panne
- Exporter le jeu et quitter l'installation
- Rétention
- Dépannage sur Clever Cloud
- Coûts et démontage
Reality Bridge et connecteurs (16)
- Le Reality Bridge : ce que c'est
- Démarrage rapide
- Garanties
- Installer et lancer le Bridge
- Sauvegarde et restauration
- Plusieurs tenants
- Signaux et manifeste
- La ligne de commande du Bridge
- Vue d'ensemble des connecteurs
- Connecteur email
- Connecteur Telnet
- Connecteur SSH
- Connecteur Open Badges
- Le SDK des connecteurs
- Sécurité : Biscuit et signatures
- Dépannage du Bridge et des connecteurs
Contribuer (25)
- Bienvenue
- Préparer son poste de développement
- La boucle de développement
- Avant une pull request
- Conventions
- Écrire la documentation
- Architecture
- Visite du code
- Frontières d'import
- Quels tests tournent quand
- Tests de mutation
- Le cliquet de couverture
- La référence de qualité
- La CI expliquée
- Passes de terrain
- Mesures de performance
- Publier une release
- Paquets npm
- Décisions et ADR
- Gouvernance
- Pull requests des bots
- Contribuer avec des agents IA
- Politique de sécurité
- Code de conduite
- Licences et crédits