4.5Tests automatisés avec PHPUnit
L'essentiel en 30 secondes
- Tests = code qui teste le code : PHPUnit (via Composer), assertions (
assertEquals,assertTrue…) qui échouent si le réel ≠ attendu. - 3 niveaux : unitaires (fonction isolée), intégration (avec la base), fonctionnels (comme un utilisateur) —
./vendor/bin/phpunitles lance tous. - Réflexe de Riad : tester d'abord la logique métier critique, relancer après chaque modification — la non-régression qui libère.
Mini-cas filé — Riad verrouille ses prix avant la promo
À la veille des promos, Riad craint qu'une remise ne casse ses prix à Constantine : il écrit son premier test PHPUnit sur prixTTC, ajoute les cas limites (zéro, taux nul, panier vide), puis relance toute la suite après chaque retouche. Quand un collègue modifie le calcul, le test vire au rouge AVANT la mise en ligne. Dernier jalon du fil rouge : du prototype qui « marche » à l'application pro qui prouve.
Dernier épisode du cas 4.1-4.4 — Riad boucle le niveau : architecturer, équiper, exposer, fiabiliser.
1. PHPUnit & les assertions
Tester à la main est fastidieux, incomplet et non répétable : on écrit du code qui TESTE le code, relançable à volonté. En PHP, la référence est PHPUnit (installé via Composer, lancé par ./vendor/bin/phpunit). Un test vérifie qu'une entrée donne la sortie ATTENDUE via des assertions — assertEquals($attendu, $resultat), assertTrue(...), assertNull(...) — qui échouent si la réalité diffère. Tests organisés en classes et méthodes, exécutés en masse avec rapport passés/échoués. Trois niveaux : unitaires (fonction/classe isolée), intégration (plusieurs parties, ex. avec la base), fonctionnels/bout en bout (comme un utilisateur).
2. Les bénéfices & le TDD
Les bénéfices : CONFIANCE (on sait, on ne croit pas), NON-RÉGRESSION — le majeur — (relancer après chaque modification alerte aussitôt si une retouche casse ce qui marchait), DOCUMENTATION (comportement attendu, exécutable et à jour), MEILLEURE CONCEPTION (le code testable est mieux découpé), détection PRÉCOCE (en dev, pas en prod). Laravel et Symfony intègrent PHPUnit avec des outils dédiés (bases de test, requêtes HTTP simulées). Le TDD écrit les tests AVANT le code (le test définit l'attendu, le code le fait passer) — discipline qui améliore la conception. Riad commence petit : logique critique d'abord, pas 100 % d'emblée.
🔎 Exemple concret — 🔎 Exemple concret — Premier test de prix TTC
Le premier test de Riad, avec les API réelles de PHPUnit :
prixTTC(100, 0.20) → attendu 120.0 (assertEquals)
prixTTC(0, 0.20) → attendu 0 (cas limite)
Lancer → ./vendor/bin/phpunit → OK (2 tests, 2 assertions)
Retouche → relancer → vert = rien de cassé
Lecture : une entrée, un attendu, une assertion — puis la boucle.
Leçon : les cas limites attrapent les bugs que la démo rate.
Vocabulaire de la section
- Tests automatisés / PHPUnit
- Code qui TESTE votre code (relançable à volonté) au lieu de vérifier à la main. PHPUnit est le standard PHP (via Composer).
Exemple simple : Riad lance ./vendor/bin/phpunit et obtient son rapport en secondes.
Ce que ce n'est pas : une vérification manuelle unique dans le navigateur.
Réflexe : tout comportement critique mérite son test.
- Assertions
- Vérifications du test : assertEquals(attendu, résultat), assertTrue, assertNull… — échouent si le réel ≠ attendu.
Exemple simple : Riad affirme assertEquals(120, prixTTC(100, 0.20)).
Ce que ce n'est pas : un echo « ça a l'air bon » sans comparaison stricte.
Réflexe : attendu d'abord, réel ensuite, message clair.
- Niveaux de tests
- Unitaires (isolé), intégration (plusieurs parties, ex. avec la base), fonctionnels/bout en bout (comme un utilisateur).
Exemple simple : Riad teste prixTTC en unitaire, la commande avec sa base en intégration.
Ce que ce n'est pas : un seul gros test qui mélange tout.
Réflexe : pyramide : beaucoup d'unitaires, peu de bout en bout.
- Bénéfices des tests
- Confiance, NON-RÉGRESSION (détecter ce qu'une modif casse), documentation, meilleure conception, détection précoce.
Exemple simple : La suite de Riad attrape une remise cassée avant la promo.
Ce que ce n'est pas : découvrir la casse par un ticket client en production.
Réflexe : suite verte exigée avant chaque livraison.
- TDD (Test-Driven Development)
- Écrire les tests AVANT le code (le test définit l'attendu, le code le fait passer) ; discipline qui améliore la conception.
Exemple simple : Riad écrit le test de remise avant la fonction, puis code jusqu'au vert.
Ce que ce n'est pas : coder au hasard puis tester pour « valider » après coup.
Réflexe : rouge → vert → refactor : le cycle TDD.
En pratique — En pratique — Fiabiliser son code avec des tests
- Installez PHPUnit (via Composer) et écrivez un premier test unitaire d'une fonction (entrée → attendu, assertEquals…).
- Lancez avec ./vendor/bin/phpunit, lisez le rapport ; ajoutez cas limites et entrées invalides.
- Écrivez un test d'intégration (fonctionnalité + base) ; sous framework, utilisez les outils de test intégrés.
- Relancez après chaque modification (non-régression) et essayez le TDD (test AVANT le code).
Script prêt à dire — annoncer la suite verte (30 s)
« C'est Riad : nos calculs critiques sont couverts par PHPUnit — unitaires, cas limites et intégration base. Chaque retouche relance la suite : verte, on livre ; rouge, on corrige avant la prod. »
À dire avant chaque livraison ; montrez la suite verte.
Modèle copier-coller — test PHPUnit (code testé)
assertEquals(120.0, prixTTC(100, 0.20));
}
public function testCasLimites(): void {
$this->assertEquals(0.0, prixTTC(0, 0.20));
$this->assertEquals(100.0, prixTTC(100, 0.0));
$this->assertTrue(prixTTC(50, 0.20) > 50);
}
}
// Lancer : ./vendor/bin/phpunit PrixTest.php
Premier pas
Un seul test sur le calcul critique : valeur immédiate, habitude installée.
Logique à risque
Comme Riad : calculs, règles métier, cas limites et invalides — là où les bugs coûtent cher.
Sous framework
Bases de test et requêtes HTTP simulées de Laravel/Symfony pour l'intégration.
Équipe qui grandit
Suite verte exigée avant merge : la non-régression devient un rituel collectif.
.env.testing hors Git) et garder les données personnelles hors des jeux de test. Contenu pédagogique, exemples avec données fictives.✓ Bonnes pratiques
- Tester la logique critique en priorité.
- Relancer après chaque modification.
- Essayer le TDD sur une petite fonction.
✗ Pièges fréquents
- Croire que « ça marche » dispense de tester.
- Viser 100 % de couverture d'emblée.
- Ne tester qu'à la main, une fois.
Points clés à retenir
- TESTS AUTOMATISÉS (PHPUnit, standard PHP) : du code qui TESTE le code. ASSERTIONS (assertEquals…) si réel ≠ attendu.
- NIVEAUX : UNITAIRES (isolé), INTÉGRATION (avec base), FONCTIONNELS (comme un utilisateur).
- BÉNÉFICES : CONFIANCE, NON-RÉGRESSION (relancer après chaque changement — le majeur), documentation, CONCEPTION.
- Frameworks intègrent PHPUnit. TDD = tests AVANT le code. INDISPENSABLE en prod — sépare prototype et app PRO.
Défi 48h — appliquez demain
Écrivez 2 tests PHPUnit sur votre fonction la plus critique (1 cas normal + 1 cas limite) et relancez après 1 retouche.
- Je peux expliquer PHPUnit, assertions, niveaux.
- Je sais lancer la suite et lire le rapport.
- J'ai 2 tests verts sur ma logique critique.
Questions fréquentes
Les tests semblent une perte de temps quand « ça marche déjà » : pourquoi tester ?
Parce que « ça marche » ne vaut que pour les cas vérifiés à la main, aujourd'hui. Demain, chaque modification risque une régression silencieuse — sans tests, il faudrait tout re-vérifier à la main, ce qu'on ne fait jamais. Les tests apportent confiance (on sait), non-régression (alerte immédiate), documentation vivante du comportement, meilleure conception (le testable est mieux découpé) et détection précoce — infiniment moins chère qu'en production.
Comment commencer sans être submergé — que tester en priorité ?
Progressif, pas 100 % d'emblée : logique métier critique (calculs, règles — là où un bug coûte cher), code complexe/à risque ou qui casse souvent, cas limites et entrées invalides (zéro, extrêmes, vides — là où se cachent les bugs), code réutilisé (un bug s'y propage partout). Moins prioritaire au début : trivial (getters), affichage pur. Méthode : Arrange-Act-Assert — préparer, agir, vérifier.
Quel est le bénéfice majeur des tests automatisés ?