Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,16 @@
"print(\"Série :\", _redact(SERIE.name))"
]
},
{
"cell_type": "markdown",
"id": "15588aa1",
"metadata": {},
"source": [
"### Lecture du résultat\n",
"\n",
"Le setup rend la localisation du module **sans exposer de chemin absolu** : `Module : 06-nouveautes-v0.10`, `Spec : 06-nouveautes.spec.ts — présent`, `Série : Playwright-OWUI`. C'est la discipline de la série entière : un banc de tests qui imprime `C:\\Users\\...` dans ses sorties rendrait les notebooks non reproductibles d'une machine à l'autre (et polluerait les attests). La ligne qui compte est `Spec : ... — présent` : le setup a trouvé le spec TypeScript que ce notebook va analyser — le carnet est la couche pédagogique posée **sur** un banc réel, pas à côté. Si cette ligne disait `absent`, tout le reste du module serait à relire : c'est la pré-condition de toutes les suivantes."
]
},
{
"cell_type": "markdown",
"id": "a635be85",
Expand Down Expand Up @@ -236,6 +246,16 @@
" print(\"Spec introuvable — voir le message de la cellule Setup.\")"
]
},
{
"cell_type": "markdown",
"id": "69024c99",
"metadata": {},
"source": [
"### Lecture du résultat\n",
"\n",
"La lecture **statique** du banc rend la structure sans l'exécuter : `2 bloc(s) describe, 7 test(s) déclaré(s)` — exactement les deux familles du §1 (`06a — API`, `06b — UI`) et les sept tests attendus, du listing mémoire (`endpoint disponible`, `cycle add/list/delete`) aux deux tests UI (raisonnement, compaction). Noter le suffixe `« v0.10 »` dans les noms de `describe` : il fait partie du **contrat** — un lecteur du rapport CI voit immédiatement ce que la tranche certifie. Et le test `dossiers d'équipe — partage entre comptes (exercice)` est déjà étiqueté « exercice » dans son nom : le banc déclare lui-même sa dépendance à une configuration que l'instance ne fournit pas toujours. Cette mesure sans exécution prépare le §5, qui rejouera le listing avec le vrai runner."
]
},
{
"cell_type": "markdown",
"id": "c8c7b69f",
Expand Down Expand Up @@ -308,6 +328,16 @@
" print(f\"{ex} -> {version_probable(ex)}\")"
]
},
{
"cell_type": "markdown",
"id": "435869f1",
"metadata": {},
"source": [
"### Lecture du résultat\n",
"\n",
"Deux souvenirs, deux verdicts — et la discrimination tient tout entière dans le champ `type`. `{'id': 'a1', 'content': 'aime les schémas', 'type': 'context'} → v0.10+` : la donnée porte le champ introduit par la refonte mémoire, c'est la **preuve de version**. `{'id': 'b2', 'content': 'note libre'} → antérieure à v0.10` : la même donnée sans le champ, la signature d'une instance d'avant la refonte. Rien d'autre ne diffère entre les deux entrées — ni la longueur du contenu, ni l'id : c'est bien la **forme de la donnée** qui tranche, pas son contenu. C'est le principe de *feature detection* appliqué à une API vivante : on n'interroge pas la version par un endpoint de diagnostic, on la lit sur le premier objet créé."
]
},
{
"cell_type": "markdown",
"id": "994bf7ca",
Expand Down Expand Up @@ -378,6 +408,16 @@
" print(f\"configuré={configure}, bloc={bloc} -> {verdict_raisonnement(configure, bloc)}\")"
]
},
{
"cell_type": "markdown",
"id": "fce9d693",
"metadata": {},
"source": [
"### Lecture du résultat\n",
"\n",
"La table de décision rend trois sorties pour trois configurations — et les trois sont **licites**. `configuré=False, bloc=False → skip` : pas de modèle de raisonnement, la pré-condition du §4 manque, le test s'efface proprement. `configuré=True, bloc=True → passed` : le cas nominal, le bloc repliable s'affiche au-dessus de la réponse. Le troisième cas est le plus fin : `configuré=True, bloc=False → skip` — un modèle **configuré** mais qui n'émet pas de réflexion (par nature ou par réglage) n'est pas une régression de v0.10.2, c'est un état supporté. Distinguer ces trois cas est exactement ce qui sépare un banc robuste d'un banc qui rouge au moindre changement de modèle : chaque sortie porte sa **raison**, pas seulement un statut."
]
},
{
"cell_type": "markdown",
"id": "651efb49",
Expand Down Expand Up @@ -470,6 +510,16 @@
" \"Les titres ci-dessus (lecture du spec) suffisent pour raisonner sur le module.\")\n"
]
},
{
"cell_type": "markdown",
"id": "b4409f78",
"metadata": {},
"source": [
"### Lecture du résultat\n",
"\n",
"Le listing ne **lance** rien — `--list` énumère les tests que Playwright *découvrira* : leur nom complet (`[owui] › 06-nouveautes-v0.10\\06-nouveautes.spec.ts:75:3 › ...`), leur fichier et leur ligne. Deux choses se lisent ici. D'abord la structure : les 7 tests du §2 apparaissent bien, groupés sous leurs deux `describe` (`06a — API`, `06b — UI`), plus le test d'authentification du setup. Ensuite les **numéros de ligne** (`:75:3`, `:90:3`...) : ils font du listing un **contrôle statique** — si un test disparaît du listing après une refonte du spec, c'est qu'il n'est plus déclaré, et ça se voit sans exécuter un seul navigateur. C'est le seul outil de la série qui donne une mesure de couverture (tests découverts vs tests attendus) sans coût d'exécution."
]
},
{
"cell_type": "markdown",
"id": "786b7191",
Expand Down Expand Up @@ -558,6 +608,16 @@
"print(\"\\nVerdict module 06 :\", \"VERT\" if coeur_vert else \"ROUGE\")"
]
},
{
"cell_type": "markdown",
"id": "733f43d8",
"metadata": {},
"source": [
"### Lecture du résultat\n",
"\n",
"La sortie rend le verdict en une ligne : `6 passed / 1 skipped`, puis le classement automatique — cœur API **VERT** (obligatoire), optionnel UI toléré. Le test réellement **skipped** ici est le partage d'équipe (`dossiers d'équipe — partage`), et c'est le bon skip : la §6b exige un second compte, absent de la configuration courante. Noter que « raisonnement — bloc » et « compaction » sont **passed**, pas skip : l'instance a un modèle de raisonnement configuré, la pré-condition du §4 était remplie. Le verdict `VERT` du module ne dit pas « tout est passé » : il dit **le contrat du module est tenu** — cœur vert, optionnel dans les états licites (passed ou skip motivé)."
]
},
{
"cell_type": "markdown",
"id": "ccca797b",
Expand All @@ -579,6 +639,16 @@
"compare au comportement attendu décrit en commentaire."
]
},
{
"cell_type": "markdown",
"id": "4e569b3b",
"metadata": {},
"source": [
"### Exercice 1 — isolation par nettoyage\n",
"\n",
"Mime le pattern d'isolation du §2 sur un cas réduit : `deja_nettoye=True → doit_nettoyer=?` et `deja_nettoye=False → doit_nettoyer=?`. Deux pièges à éviter en implémentant. Premièrement, la seconde combinaison est celle qui compte : le nettoyage est **inconditionnel** dans un bloc `finally` — on ne décide pas de nettoyer en regardant l'état, on nettoie parce que le test a pu créer quelque chose ; la décision `doit_nettoyer` dépend de « ai-je créé une ressource dans ce test ? », jamais de l'état global de l'instance. Deuxièmement, le placeholder rend `False` dans les deux cas parce qu'il n'a rien créé : l'exécution du squelette sert à observer le mauvais comportement, pas à le conserver — l'attendu après correction (`False` puis `True`) est rappelé en commentaire."
]
},
{
"cell_type": "code",
"execution_count": 7,
Expand Down Expand Up @@ -622,6 +692,16 @@
"# Attendu après correction : False puis True."
]
},
{
"cell_type": "markdown",
"id": "d22baa9f",
"metadata": {},
"source": [
"### Exercice 2 — détecter la version par la forme\n",
"\n",
"Rejoue la *feature detection* du §3 sur deux données minimales : `{'type': 'context'}` porte le champ de version → `v0.10+` ; `{}` ne porte rien → `antérieure`. La question que le placeholder laisse ouverte (`-> ?`) est le cœur du geste : la fonction doit **rendre un verdict**, pas lever — une donnée sans champ est un état documenté (instance ancienne), pas une erreur. C'est exactement la discipline qui permet à un même banc de tests de tourner sur des versions d'instance différentes sans faux rouges."
]
},
{
"cell_type": "code",
"execution_count": 8,
Expand Down Expand Up @@ -664,6 +744,16 @@
"# Attendu après correction : \"v0.10+\" puis \"antérieure\"."
]
},
{
"cell_type": "markdown",
"id": "8eef4a2f",
"metadata": {},
"source": [
"### Exercice 3 — skip ou échec ?\n",
"\n",
"Explore la frontière **skip vs échec**. Les trois combinaisons demandées se lisent ainsi : `précondition=False` (quel que soit le reste) → le test n'a pas son environnement, la bonne réponse est le **skip**, jamais un échec. `précondition=True, assertion=True` → passed, le cas nominal. `précondition=True, assertion=False` → c'est la **seule vraie régression** : tout est en place, la fonctionnalité ne marche pas — le test doit échouer bruyamment. Un placeholder qui rend `passed` ici est un piège pédagogique volontaire : c'est au lecteur de décider que cette case doit lever, pas s'effacer — c'est la différence entre **skip** (pré-condition non remplie) et **échec** (pré-condition remplie, assertion fausse) qui distingue un test robuste d'un test qui masque une régression."
]
},
{
"cell_type": "code",
"execution_count": 9,
Expand Down Expand Up @@ -776,4 +866,4 @@
},
"nbformat": 4,
"nbformat_minor": 5
}
}
Loading
Loading