Stratégie de tests¶
Philosophie¶
Règle d'or
Un test doit tester un comportement métier, pas une implémentation technique. Préférez "quand une partie est créée, une invitation est envoyée" à "quand create() est appelé, save() est appelé sur le mock".
Pyramide de tests¶
/\
/E2E\ Playwright — Parcours utilisateurs complets
/─────\
/ Intég \ Pest Feature — Endpoints API, DB
/─────────\
/ Unitaire \ Pest Unit + Vitest — Services, composants isolés
/─────────────\
| Couche | Outil | Commande | Couverture cible |
|---|---|---|---|
| Unitaires backend | Pest PHP | make test | 90%+ |
| Intégration backend | Pest PHP Feature | make test | 80%+ |
| Architecture | Pest Arch | make test-arch | 100% boundaries |
| Unitaires frontend | Vitest | make test-frontend | 80%+ |
| E2E | Playwright | make test-e2e | Parcours critiques |
Couverture de code¶
- Seuil minimum : 80% (lignes, fonctions, branches, statements)
- Objectif : 90%+
- Outil backend : pcov (extension PHP) —
--coverage --min=80 - Outil frontend :
@vitest/coverage-v8
Exclusions de couverture backend (phpunit.xml)¶
Les fichiers suivants sont exclus du calcul (pas de logique métier) :
<source>
<exclude>
<directory>app/Providers/</directory> <!-- Service providers (configuration) -->
<file>app/Models/User.php</file> <!-- Modèle Eloquent auto-généré -->
</exclude>
</source>
Isolation de la base de données de test¶
PHPUnit 12 + Docker : balises <server> obligatoires
Lorsque les tests PHPUnit/Pest tournent dans un conteneur Docker, les variables d'environnement injectées par Docker Compose (DB_DATABASE, etc.) sont présentes dans $_SERVER. Or Laravel lit $_SERVER en priorité via son helper env(). Les balises <env force="true"/> de PHPUnit 12 mettent à jour putenv() et $_ENV mais pas $_SERVER. Il faut donc aussi des balises <server> dans phpunit.xml pour garantir que les tests utilisent bien primatch_test et non la base principale.
<!-- phpunit.xml — les deux types de balises sont nécessaires -->
<env name="DB_DATABASE" value="primatch_test" force="true"/>
<server name="DB_DATABASE" value="primatch_test"/>
Sans les balises <server>, RefreshDatabase exécute migrate:fresh sur la base principale, vidant toutes les données utilisateur et métier.
Configuration frontend (vitest.config.ts)¶
make test-coverage # Backend avec couverture HTML
make test-coverage-frontend # Frontend avec couverture LCOV + HTML
Quoi tester par couche¶
Tests unitaires (Domain)¶
- ✅ Services métier (
MatchService, etc.) - ✅ Value Objects (Score, Niveau)
- ✅ DTOs (validation, transformation)
- ❌ Pas les Repositories (testés en intégration)
Tests d'intégration (Http + DB)¶
- ✅ Controllers (endpoint → réponse JSON)
- ✅ Form Requests (validation des inputs)
- ✅ Repositories (vraie DB de test
primatch_test) - ✅ Events et Listeners
Tests E2E (Playwright)¶
- ✅ UC-AUTH-001 : Inscription par OTP
- ✅ UC-AUTH-002 : Connexion par OTP
- ✅ UC-PARTIE-001 : Créer une partie
- ✅ UC-PARTIE-004 : Saisir et valider un score (4 joueurs)
Cas à toujours couvrir¶
Pour chaque fonctionnalité :
- Flux heureux (happy path)
- Validation (données invalides → 422)
- Authentification (non connecté → 401)
- Autorisation (mauvais rôle → 403)
- Cas limites (ressource inexistante → 404)
Pre-commit hooks (Husky)¶
Ne jamais utiliser --no-verify
Le hook pre-commit exécute automatiquement à chaque commit :
- lint-staged — Lint des fichiers modifiés (ESLint + Pint)
- TypeScript — Vérification des types (
tsc --noEmit) - Build frontend — Vérifie que le build de production passe
- PHPStan — Analyse statique PHP niveau 6
- Pest — Tests backend + couverture ≥ 80%
- Vitest — Tests frontend (conditionnel : ignoré s'il n'y a pas encore de fichiers
*.test.ts(x))
Tests frontend conditionnels
Les tests Vitest sont ignorés automatiquement s'il n'y a pas encore de fichiers de test dans frontend/src/. Cela permet de travailler en early-stage sans blocage.