Documentation des Tests
Guide complet sur la structure, les patterns et les helpers de test pour garantir la qualité et la cohérence des tests dans le projet.
1. Vue d'ensemble
Organisation modulaire
Un module = une structure de tests dans tests/Feature/Specifics/ et tests/Unit/Specifics/
Séparation Feature/Unit
Tests Feature pour les intégrations, Unit pour les tests unitaires (sans base de données, avec mocks)
Framework : Pest
Framework de tests principal avec syntaxe expressive et helpers Laravel
2. Structure Feature
Organisation
tests/Feature/Specifics/
├── {ModuleName}/
│ ├── Actions/ # Tests d'intégration Actions
│ ├── Queries/ # Tests d'intégration Queries
│ ├── Services/ # Tests d'intégration Services
│ └── Models/ # Tests d'intégration Models
└── Examples/ # Exemples de référence
├── Actions/
├── Queries/
└── Services/
Actions/
Tests d'intégration pour les Actions métier.
Exemple : CreateFeedbackActionTest.php
- • Création réussie
- • Validation des données
- • Gestion des erreurs
- • Transactions
- • Événements déclenchés
Queries/
Tests d'intégration pour les Queries.
Exemple : GetFeedbackListQueryTest.php
- • Filtres
- • Tri
- • Pagination
- • Eager loading
- • Relations
Services/
Tests d'intégration pour les Services.
Exemple : FeedbackServiceTest.php
- • Orchestration de plusieurs Actions/Queries
- • Logique métier complexe
- • Gestion des erreurs
- • Transactions
Models/
Tests d'intégration pour les Models.
Exemple : FeedbackTest.php
- • Relations
- • Accessors/Mutators
- • Scopes
- • Events
- • Concerns
3. Structure Unit
Même organisation que Feature, mais pour les tests unitaires (sans base de données, avec mocks).
tests/Unit/Specifics/
├── {ModuleName}/
│ ├── Actions/ # Tests unitaires Actions
│ ├── Queries/ # Tests unitaires Queries
│ ├── Services/ # Tests unitaires Services
│ └── Models/ # Tests unitaires Models
└── Examples/ # Exemples de référence
4. Patterns de test
Pattern AAA (Arrange, Act, Assert)
it('creates a feedback successfully', function () {
// Arrange : Préparer les données
$user = $this->actingAsUser();
$data = ['title' => 'Test Feedback'];
// Act : Exécuter l'Action
$action = new CreateFeedbackAction();
$result = $action->execute($user, $data);
// Assert : Vérifier le résultat
expect($result)
->toBeInstanceOf(Feedback::class)
->and($result->title)->toBe('Test Feedback');
});
Test d'Action
Cas à tester :
✅ Succès
- • Création réussie
- • Données correctes
- • Relations créées
✅ Validation
- • Données invalides
- • Contraintes métier
- • Permissions
✅ Transactions
- • Rollback en cas d'erreur
- • Atomicité des opérations
✅ Événements
- • Événements déclenchés
- • Données de l'événement
Test de Query
Cas à tester :
✅ Filtres
- • Filtres simples
- • Filtres multiples
- • Filtres optionnels
✅ Pagination
- • Pagination par défaut
- • Pagination personnalisée
- • Nombre total d'éléments
✅ Tri
- • Tri par défaut
- • Tri personnalisé
- • Tri ascendant/descendant
✅ Eager Loading
- • Relations chargées
- • Performance (N+1)
5. Helpers de test
Traits
UsesDatabase
Helpers pour base de données : tests/Concerns/UsesDatabase.php
uses(UsesDatabase::class);
// Méthodes disponibles :
$this->setUpDatabase();
$this->inTransaction(function () { /* ... */ });
$this->seedDatabase('UserSeeder');
$this->assertTableCount('users', 5);
$this->assertRecordExists('users', ['email' => 'test@example.com']);
$this->assertRecordNotExists('users', ['email' => 'deleted@example.com']);
UsesFactories
Helpers pour factories : tests/Concerns/UsesFactories.php
uses(UsesFactories::class);
// Méthodes disponibles :
$user = $this->createUser(['email' => 'test@example.com']);
$users = $this->createUsers(5);
$user = $this->actingAsUser(['role' => 'admin']);
$feedback = $this->createModel(Feedback::class, ['title' => 'Test']);
$feedbacks = $this->createModels(Feedback::class, 10);
$feedback = $this->makeModel(Feedback::class, ['title' => 'Test']);
Fonctions globales
Exposées dans tests/Pest.php
// Tester une Action
$result = testAction(CreateFeedbackAction::class, $user, $data);
// Tester une Query
$result = testQuery(GetFeedbackListQuery::class, $status, $perPage);
// Tester un Service
$result = testService(FeedbackService::class, 'createFeedback', $data);
6. Conventions de nommage
Fichiers de test
Format : {ClassName}Test.php
- •
CreateFeedbackActionTest.php - •
GetFeedbackListQueryTest.php - •
FeedbackServiceTest.php
Tests Pest
Utiliser it() avec descriptions claires
it('creates a feedback successfully', function () {
// Test
});
7. Création d'un nouveau test
Checklist
-
Identifier le module (
{ModuleName}) - Identifier le type (Action, Query, Service, Model)
- Identifier le niveau (Feature ou Unit)
- Créer le fichier au bon endroit
- Suivre les conventions de nommage
- Utiliser les helpers de test
Exemple : Créer un test d'Action
Étape 1 : Identifier le module
Module : FeedbackHub, Action : CreateFeedbackAction
Étape 2 : Créer le fichier
Chemin : tests/Feature/Specifics/FeedbackHub/Actions/CreateFeedbackActionTest.php
Étape 3 : Écrire le test
use App\Models\User;
use App\Specifics\FeedbackHub\Actions\CreateFeedbackAction;
use App\Specifics\FeedbackHub\Models\Feedback;
uses(UsesDatabase::class, UsesFactories::class);
it('creates a feedback successfully', function () {
$user = $this->actingAsUser();
$action = new CreateFeedbackAction();
$feedback = $action->execute($user, [
'title' => 'Test Feedback',
'description' => 'Test Description',
]);
expect($feedback)
->toBeInstanceOf(Feedback::class)
->and($feedback->title)->toBe('Test Feedback');
});
8. Commandes utiles
# Exécuter tous les tests
php artisan test
# Exécuter les tests d'un module spécifique
php artisan test --filter=FeedbackHub
# Exécuter les tests unitaires uniquement
php artisan test --testsuite=Unit
# Exécuter les tests feature uniquement
php artisan test --testsuite=Feature
# Exécuter un fichier de test spécifique
php artisan test tests/Feature/Specifics/FeedbackHub/Actions/CreateFeedbackActionTest.php
# Exécuter avec couverture de code
php artisan test --coverage
# Exécuter en mode parallèle
php artisan test --parallel
9. Bonnes pratiques
Organisation
- • Un test = un cas : Un test ne doit tester qu'un seul cas
- • Nommage clair : Le nom du test doit décrire ce qui est testé
- • AAA Pattern : Arrange, Act, Assert
Données de test
- • Factories : Utiliser les factories pour créer des données
- • Fixtures : Éviter les données hardcodées
- • Isolation : Chaque test doit être indépendant
Assertions
- • Expectations : Utiliser
expect()de Pest - • Assertions Laravel : Utiliser
$this->assert*()pour la base de données - • Messages clairs : Messages d'erreur explicites
Performance
- • RefreshDatabase : Utiliser
RefreshDatabasepour isoler les tests - • Transactions : Utiliser les transactions pour les tests rapides
- • Eager Loading : Vérifier l'eager loading pour éviter N+1
Résumé
Structure
| Niveau | Chemin |
|---|---|
| Feature | tests/Feature/Specifics/{Module}/ |
| Unit | tests/Unit/Specifics/{Module}/ |
Checklist de création
- Structure créée pour le module
- Fichier de test créé au bon endroit
- Conventions de nommage respectées
- Test écrit avec Pest
- Test passe avec succès