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 RefreshDatabase pour 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

Prendre rendez-vous