Aller au contenu

Le bilan : tous les tests verts, le carnet des failles

Temps 2 · séance 2 · ~15 min

Les slides du chapitre (PDF)PDF

  • Dire ce que prouve composer test vert, et à quoi sert le carnet des failles.
  • Lancer composer test et lire ses trois étapes jusqu'au vert.
  • Réparer une mise en forme refusée, une erreur de PHPStan, un test repassé au rouge ou une base pas migrée.
  • Enregistrer vos corrections dans un commit et les envoyer sur votre fork avec git push.
  • Relire votre carnet des failles et écrire, pour chaque faille, un endroit précis de votre portfolio.

1. Comment savoir que c'est réussi

Au temps 2, rien ne se remet. C'est réussi quand composer test est vert de bout en bout, et vous le vérifiez vous-même, sur votre machine.

composer test vert prouve que les failles des chapitres 2.02 à 2.10 sont corrigées sans casser le jeu. Chaque faille a ses tests, rouges au départ. Les tests du jeu et du kit doivent rester verts. Si un seul échoue, la commande le dit.

Le carnet des failles (gabarit WordDOCX, PDFPDF) prouve autre chose : vous reconnaissez ces failles dans votre propre code, où personne ne les a placées exprès. Il ne se rend pas. Il est pour vous : il sert à retrouver ces failles dans votre portfolio, aujourd'hui et dans vos prochaines applications.

Comment savoir que c'est réussi : deux preuves. À gauche, les tests, sur votre machine : composer test vert de bout en bout, avec Pint, PHPStan et les 89 tests, qui prouve que les failles des chapitres 2.02 à 2.10 sont corrigées sans casser le jeu ni le kit. À droite, le carnet des failles, pour vous : pour chaque faille, la règle et l'endroit de votre portfolio où elle s'applique, ou nulle part et la raison, qui prouve que vous reconnaissez ces failles dans votre propre code. En bas : rien ne se remet, vous vérifiez vous-même que composer test est vert

Deux questions font le bilan. composer test passe-t-il en entier ? Dans le carnet, chaque faille a-t-elle sa règle et un endroit précis de votre portfolio, ou une raison honnête de n'en avoir aucun ?

2. La dernière vérification

Au chapitre 2.01, php artisan test se terminait par 24 failed, 61 passed. Lancez-le une dernière fois :

php artisan test
   PASS  Tests\Unit\MoneyTest
  ✓ cents are displayed as euros with (1050, '10,50 €')                0.01s
…
   PASS  Tests\Feature\Flaws\Flaw02AccessControlTest
  ✓ a player cannot open the edit page of someone else's creature       0.10s
…
   PASS  Tests\Feature\Flaws\Flaw10ThrottleTest
  ✓ the sixth gift code tried within a minute is refused                0.13s

   PASS  Tests\Feature\Game\GameTest
…
  Tests:    89 passed (368 assertions)
  Duration: 9.23s

Le tableau de bord compte quatre tests de plus qu'au départ : ceux de MoneyTest, que vous avez écrits au chapitre 2.07.

Le tableau de bord de php artisan test à la fin du temps 2, ligne par ligne comme au chapitre 2.01. Séance 1 : 2.02 contrôle d'accès, 6 verts · 2.03 assignation de masse, 1 · 2.04 props publiques, 1 · 2.05 XSS, 1 · 2.06 injection SQL, 2. Séance 2 : 2.07 les centimes, 4 · 2.08 le prix du navigateur, 6 · 2.09 l'achat atomique, 3 · 2.10 la limitation de débit, 1. En tout 89 verts et 0 rouge : 42 du kit, 18 du jeu, 25 des failles, 4 de Money. En dessous, composer test : Pint PASS, PHPStan OK, 89 passed

Lancez ensuite le critère de réussite :

composer test
   INFO  Configuration cache cleared successfully.

  ....................................................................................................

  ──────────────────────────────────────────────────────────── Laravel
    PASS   ........................................................... 100 files

Note: Using configuration file …\tamagotchi\phpstan.neon.

 [OK] No errors

   PASS  Tests\Unit\ExampleTest
  ✓ that true is true                                                   0.44s
…
  Tests:    89 passed (368 assertions)
  Duration: 8.31s

Lisez la sortie dans l'ordre. Pint a relu la mise en forme de 100 fichiers, sans rien à redire. PHPStan a analysé le code sans erreur. Les 89 tests sont verts. Au chapitre 2.01, la même commande s'arrêtait à PHPStan, sur la faille du chapitre 2.06.

3. Quand ce n'est pas vert

composer test s'arrête à la première étape qui échoue. Le nom du script en échec, à la fin de la sortie, dit où regarder.

Pint refuse la mise en forme

  ...................................................................................................⨯

  ──────────────────────────────────────────────────────────── Laravel
    FAIL   .................................................. 100 files, 1 style issue
  ⨯ app\Http\Controllers\CreatureController.php     method_argument_space, spaces_inside_parentheses

Script pint --parallel --test handling the lint:check event returned with error code 1

Ici, une ligne de edit() était écrite Gate::authorize( 'update',$creature );. Le code fonctionne, mais il ne suit pas les règles de mise en forme du projet. Le script composer lint du kit lance Pint en mode correction :

composer lint
    FIXED   ......................................... 100 files, 1 style issue fixed
  ✓ app\Http\Controllers\CreatureController.php     method_argument_space, spaces_inside_parentheses

Relancez composer test.

PHPStan signale une ligne

 ------ -----------------------------------------------------------------------------------
  Line   app\Support\Money.php
 ------ -----------------------------------------------------------------------------------
  14     Method App\Support\Money::format() should return string but returns string|false.
         🪪  return.type
 ------ -----------------------------------------------------------------------------------

 [ERROR] Found 1 error

Script phpstan analyse handling the types:check event returned with error code 1

PHPStan donne le fichier, la ligne et la raison. Ici, le (string) du chapitre 2.07 manquait devant Number::currency(), qui peut rendre false. Corrigez la ligne, puis relancez PHPStan seul avec composer types:check, jusqu'à [OK] No errors.

Un test déjà vert repasse au rouge

Une correction incomplète peut rester invisible jusqu'à un chapitre suivant. Dans cet exemple, le solde est sorti de #[Fillable] au chapitre 2.03, mais les deux contrôleurs qui le modifient n'ont pas été adaptés comme ce chapitre le demandait. PurchaseController et GiftCodeController le changent encore par $user->update(['balance_cents' => …]) :

   FAIL  Tests\Feature\Flaws\Flaw07CentsTest
  ⨯ three sweets at 0,10 € cost exactly 0,30 €
   FAIL  Tests\Feature\Flaws\Flaw08ClientPriceTest
  ⨯ a price sent by the browser is ignored
…
  Failed asserting that 30 is identical to 0.
…
  Tests:    2 failed, 87 passed (366 assertions)

update() ignore une clé absente de #[Fillable] sans rien dire : l'achat ne coûte plus rien, et le code cadeau ne crédite plus rien. Les tests du jeu restent verts, car aucun ne relit le solde. Ce sont les tests des chapitres 2.07 et 2.08 qui le voient. Le geste est celui du chapitre 2.03 : une affectation, puis save().

$user->balance_cents -= $total;
$user->save();

Les tests sont verts, la page plante

Vous ouvrez tamagotchi.test/dashboard et une page d'erreur s'affiche :

TypeError
app\Support\Money.php:12

App\Support\Money::format(): Argument #1 ($cents) must be of type int, null given,
called in …\app\Http\Middleware\HandleInertiaRequests.php on line 44

Le joueur n'a pas de balance_cents, parce que la migration du chapitre 2.07 n'a pas tourné sur votre base. Les tests ne le voient pas : ils utilisent une base SQLite en mémoire, réglée dans phpunit.xml, distincte de votre base locale. RefreshDatabase, déclaré dans tests/Pest.php, y applique les migrations au début de la suite, puis annule après chaque test ce que le test a écrit. La commande suivante liste les migrations en attente :

php artisan migrate:status --pending
  Migration name ........................................... Batch / Status
  …_convert_amounts_to_cents ...................... Pending

php artisan migrate la lance et convertit les montants. php artisan migrate:fresh --seed repart du seeder.

4. Vos corrections sur votre fork

Votre dossier tamagotchi est le clone de votre fork, créé au chapitre 2.01. git push y envoie vos corrections. Rien ne se remet, mais votre travail reste ainsi sur GitHub, et vous pourrez y revenir plus tard.

Vérifiez d'abord ce que Git va enregistrer :

git status --short
 M app/Http/Controllers/CreatureController.php
 M app/Http/Controllers/EnclosureController.php
…
 M routes/web.php
?? app/Policies/
?? app/Support/
?? database/migrations/…_convert_amounts_to_cents.php
?? tests/Unit/MoneyTest.php

.env et database/database.sqlite n'apparaissent pas : le .gitignore les écarte. Le fichier .env porte la clé de l'application, et le chapitre 2.11 dit pourquoi il ne quitte jamais votre machine. La base se recrée avec migrate:fresh --seed. Enregistrez vos corrections dans un commit :

git add .
git commit -m "Failles 2.02 à 2.10 corrigées, composer test vert"
[main 14a4361] Failles 2.02 à 2.10 corrigées, composer test vert
 24 files changed, 228 insertions(+), 90 deletions(-)
 create mode 100644 app/Policies/CreaturePolicy.php
…

Envoyez ensuite ce commit sur votre fork :

git push
…
To …
   b325dcf..14a4361  main -> main

La dernière ligne dit que la branche main de votre fork est passée du commit de départ à votre commit. Ouvrez votre fork sur GitHub et vérifiez que app/Policies/CreaturePolicy.php y est.

5. Le carnet des failles, relu

Le carnet se remplit à la fin de chaque chapitre, dans le gabarit WordDOCX. Il a une ligne par faille, de 2.02 à 2.10, et un cadre pour la liste de contrôle du chapitre 2.11 : ce que vous avez vérifié sur votre portfolio en ligne. Relisez-le maintenant, ligne par ligne.

La colonne « La règle » est la plus simple : la phrase de la section « La règle » du chapitre, recopiée. La colonne « Dans mon portfolio » demande un fichier, une méthode, une route ou une page, et ce que vous y avez vérifié. Relue dans six mois, elle doit vous ramener à l'endroit exact. Voici la ligne du chapitre 2.02 pour le portfolio de Nora Benali, celui des exemples du temps 1 :

Faille La règle Dans mon portfolio
2.02 Changer le numéro dans l'adresse Chaque action sur une donnée vérifie côté serveur, avec une policy, que la personne connectée a le droit de la toucher. Un lien masqué ne protège rien. ProjectController@show : abort_if($project->published_at === null, 404) refuse un brouillon. Vérifié déconnectée sur /projets/carnet-de-recettes : 404. Back-office : pas de policy, parce que l'inscription est fermée depuis le chapitre 1.10 et que le seul compte est le mien. Le middleware auth du groupe /admin suffit. Si j'ouvre un second compte, il faudra une policy sur Admin\ProjectController.

La ligne nomme une méthode, montre la vérification faite, et donne pour le back-office une raison tirée du code. Elle dit aussi quand cette raison cessera de valoir. Comparez avec trois lignes creuses :

  • « Il faut toujours vérifier les droits. » : la règle répétée, aucun endroit.
  • « Dans les contrôleurs. » : plus tard, vous ne saurez plus lesquels, ni ce que vous y aviez vérifié.
  • « Nulle part. » : sans raison, vous ne saurez plus si vous aviez cherché.

Faites la même vérification sur votre portfolio : déconnectez-vous et ouvrez l'adresse d'un brouillon. Si son contenu s'affiche, votre portfolio laisse lire une page non publiée, et le carnet vient de trouver un trou. Écrivez-le tel quel, reprenez le contrôle du chapitre 1.16, puis corrigez-le.

6. Et après

Le projet en binôme qui suit reprend la policy du chapitre 2.02 pour ses pages d'administration et ses rôles, avec Gate::authorize() en première ligne de chaque action. Avant sa mise en ligne, il repasse par la liste de contrôle du chapitre 2.11. Votre portfolio, lui, est déjà en ligne chez OVH. Là où votre carnet a trouvé un trou, corrigez-le, relancez vos tests, puis redéployez comme au chapitre 1.22.

À retenir

  • Au temps 2, rien ne se remet : composer test vert de bout en bout vous dit que c'est réussi, et vous le vérifiez vous-même.
  • composer test enchaîne Pint, PHPStan et les tests, et s'arrête à la première étape qui échoue.
  • composer lint corrige la mise en forme que Pint refuse, et PHPStan donne le fichier et la ligne de chaque erreur.
  • Des tests verts ne disent rien de votre base locale, et php artisan migrate:status --pending liste les migrations qu'elle n'a pas reçues.
  • Votre dossier est le clone de votre fork : git add ., git commit, puis git push y envoient vos corrections, sans .env ni base.
  • Le carnet des failles est pour vous, et une bonne ligne nomme un endroit précis du portfolio et ce que vous y avez vérifié, ou dit pourquoi la règle ne s'y applique pas.