Un échec en usage fait le meilleur test
Une évaluation tirée de la production transforme un vrai échec en cas de test. C’est utile, car les clients trouvent des défauts que personne n’avait prévus. Mais leurs messages contiennent des noms, des adresses et des numéros que vous ne devez pas garder.
L’agent de la boutique échoue quatre fois cette semaine. Quelles parties de ces conversations peuvent entrer dans votre jeu de test ?
À la fin de cette leçon
Remarque
Je peux transformer un échec en usage en cas, sans garder ce qui ne doit pas l’être.
Mots-clés
| Mot | Ce que ça veut dire |
|---|---|
| Trace | l’enregistrement d’un vrai essai |
| Masquage | remplacer une donnée personnelle par un repère |
| Échantillonnage | choisir les traces à lire |
| Cas témoin | une trace réussie gardée pour montrer ce qui ne doit pas casser |
| Dérive | un jeu qui change jusqu’à ne plus mesurer la même chose |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Choisir les traces à lire
Vous ne pouvez pas lire chaque trace. L’échantillonnage choisit. Prenez chaque échec signalé par un utilisateur ou relevé par un contrôle. Ajoutez quelques traces réussies comme cas témoins, pour qu’un correctif ne casse pas ce qui marchait.
Un échec n’est un cas que lorsqu’une personne a écrit ce qui aurait dû se passer.
Exemple travaillé : six traces deviennent quatre cas
| Trace | Résultat | Ce qu’il en advient |
|---|---|---|
| t1 | échec | un cas, le courriel remplacé |
| t2 | ok | un cas témoin |
| t3 | échec | un cas, le numéro de téléphone remplacé |
| t4 | échec | un cas |
| t5 | échec | écartée : même entrée que t4 une fois masquée |
| t6 | ok | non échantillonnée |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Retirer les données personnelles avant de stocker
Le masquage remplace chaque nom, adresse et numéro par un repère comme [courriel]. Faites-le avec des règles que vous pouvez lire et tester, jamais en demandant à un modèle, et masquez aussi le texte attendu.
Puis contrôlez. Cherchez dans les cas terminés ce qui devrait avoir disparu. Un cas qui contient encore une adresse est une fuite de données dans votre jeu de test.
Empêcher le jeu de dériver
La dérive veut dire que le jeu change sans bruit, jusqu’à ce qu’un score du mois dernier ne signifie plus la même chose. Donnez au jeu un numéro de version. N’ajoutez de cas que par relecture, jamais par un script qui tourne chaque nuit.
Limitez sa taille et écartez les doublons, pour qu’un flot d’un seul défaut ne pèse pas plus que le reste.
Écrire les traces enregistrées, partie 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' '// Traces inventées d’un agent de boutique. Les personnes et les numéros sont faux.' 'const traces = [' ' { id: \"t1\", resultat: \"echec\", utilisateur: \"Remboursez la commande A17, mon courriel est [email protected]\", attendu: \"Demander quel article, puis rembourser une seule fois\" },' ' { id: \"t2\", resultat: \"ok\", utilisateur: \"Où est la commande B02 ?\", attendu: \"Dire qu’elle est expédiée\" },' ' { id: \"t3\", resultat: \"echec\", utilisateur: \"Appelez-moi au +33-6-39-98-12-34 pour la commande C11\", attendu: \"Proposer la page d’aide, ne promettre aucun appel\" },' > traces.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire les traces enregistrées, partie 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' ' { id: \"t4\", resultat: \"echec\", utilisateur: \"Où est mon colis ? [email protected]\", attendu: \"Chercher la commande, puis demander le numéro\" },' ' { id: \"t5\", resultat: \"echec\", utilisateur: \"Où est mon colis ? [email protected]\", attendu: \"Chercher la commande, puis demander le numéro\" },' ' { id: \"t6\", resultat: \"ok\", utilisateur: \"Bonjour\", attendu: \"Saluer le client\" },' '];' 'module.exports = { traces };' >> traces.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire le constructeur de cas, partie 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { traces } = require(\"./traces\");' 'function masquer(texte) {' ' return texte.split(\" \").map(function (mot) {' ' let coeur = mot;' ' let fin = \"\";' ' while (coeur.length > 0 && \".,?\".includes(coeur[coeur.length - 1])) {' ' fin = coeur[coeur.length - 1] + fin;' ' coeur = coeur.slice(0, -1);' ' }' ' if (coeur.includes(\"@\")) return \"[courriel]\" + fin;' ' const chiffres = coeur.split(\"\").filter(function (c) { return c >= \"0\" && c <= \"9\"; }).length;' ' const simple = coeur.split(\"\").every(function (c) { return (c >= \"0\" && c <= \"9\") || c === \"+\" || c === \"-\"; });' ' if (simple && chiffres >= 7) return \"[telephone]\" + fin;' ' return mot;' ' }).join(\" \");' '}' > cas.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire le constructeur de cas, partie 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const vus = [];' 'const cas = [];' 'const ecartes = [];' 'let nbOk = 0;' 'traces.forEach(function (trace) {' ' const un = { entree: masquer(trace.utilisateur), attendu: masquer(trace.attendu), source: trace.id };' ' if (trace.resultat === \"ok\") {' ' if (nbOk % 2 === 0) { un.genre = \"témoin\"; cas.push(un); }' ' nbOk = nbOk + 1;' ' return;' ' }' ' if (vus.includes(un.entree)) { ecartes.push(trace.id); return; }' ' vus.push(un.entree);' ' un.genre = \"échec\";' ' cas.push(un);' '});' >> cas.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire le constructeur de cas, partie 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'cas.forEach(function (un, rang) {' ' console.log(\"Cas \" + (rang + 1) + \" (\" + un.genre + \", de \" + un.source + \") : \" + un.entree);' '});' 'console.log(\"Écarté comme doublon : \" + ecartes.join(\", \"));' 'const restes = cas.filter(function (un) { return un.entree.includes(\"@\") || un.entree.includes(\"12-34\"); });' 'console.log(\"Cas contenant encore des données personnelles : \" + restes.length);' 'console.log(\"Jeu version 1 avec \" + cas.length + \" cas\");' >> cas.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Construire des cas depuis les traces
docker exec -w /home/node/project agent node cas.jsAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Ce que le constructeur affiche
| Ligne | Ce qu’elle montre |
|---|---|
| Cas 1 à 4 | trois échecs et un témoin, données personnelles remplacées |
| Écarté | t5 |
| Données personnelles restantes | 0 |
| Jeu | version 1 avec 4 cas |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
À vous
Astuce
Dans traces.js, ajoutez une trace dont le texte contient une adresse comme [email protected], puis relancez. Le cas doit montrer [courriel]. Supprimez ensuite l’appel à masquer et voyez ce qui fuit.
Une erreur fréquente
Attention
Beaucoup ne masquent que le message de l’utilisateur. Le texte attendu, l’identifiant de la trace et les arguments d’outil peuvent contenir la même adresse. Masquez chaque champ que vous gardez, ou ne gardez que ceux qu’il faut, et testez le jeu terminé pour ce qui devrait avoir disparu.