# Un jeu de fixtures partagé entre classes de test, plutôt qu’un setUp répété

> Recréer les mêmes objets de test dans chaque classe alourdit une suite sans raison. Voici comment mutualiser un jeu de fixtures entre plusieurs classes PHPUnit.

- Auteur : WordPress Développement
- Publié le : 2023-11-18
- Mis à jour le : 2023-11-18
- Catégorie : Tests
- URL : https://www.wpmoderne.fr/tests/fixtures-partagees-entre-classes-test-plutot-que-setup/

## L’essentiel

- setUpBeforeClass et une méthode statique partagée évitent de recréer les mêmes objets
- Un trait dédié aux fixtures se réutilise dans plusieurs classes de test sans héritage lourd
- La mutualisation réduit aussi le temps d'exécution, pas seulement la duplication de code

Six classes de test différentes, six méthodes `setUp()` qui recréent, presque à l'identique, la même arborescence de catégories et le même jeu d'articles de démonstration. C'est le point de départ de ce cas : une extension de gestion éditoriale dont la suite de tests avait grossi organiquement, chaque nouvelle classe copiant le bloc de préparation de la précédente plutôt que de le mutualiser.

Le symptôme le plus visible n'était pas la duplication de code en elle-même, mais la durée d'exécution de la suite complète : chaque classe recréait sa propre arborescence en base de données, alors que rien n'empêchait de la construire une seule fois pour un ensemble de classes qui en avaient l'usage identique.

## Le réflexe initial : setUp répété

La méthode `setUp()` de PHPUnit s'exécute avant chaque méthode de test, ce qui garantit un état propre à chaque cas, mais ce n'est pas toujours nécessaire : quand plusieurs classes de test ont besoin exactement du même jeu de données en lecture seule, reconstruire ce jeu de données à chaque méthode gaspille du temps sans apporter de garantie supplémentaire.

```
class ArticlesParCategorieTest extends WP_UnitTestCase
{
    private int $categorieParenteId;

    public function setUp(): void
    {
        parent::setUp();
        $this->categorieParenteId = self::factory()->category->create(['name' => 'Actualités']);
        self::factory()->category->create(['name' => 'Locales', 'parent' => $this->categorieParenteId]);
        self::factory()->post->create_many(5, ['post_category' => [$this->categorieParenteId]]);
    }
}
```

## Mutualiser avec setUpBeforeClass

Quand le jeu de données reste identique pour l'ensemble des méthodes d'une même classe, `wpSetUpBeforeClass()` — la variante statique fournie par `WP_UnitTestCase`, appelée une seule fois avant toutes les méthodes de la classe — évite de recréer les mêmes objets à chaque test :

```
class ArticlesParCategorieTest extends WP_UnitTestCase
{
    private static int $categorieParenteId;

    public static function wpSetUpBeforeClass(WP_UnitTest_Factory $factory): void
    {
        self::$categorieParenteId = $factory->category->create(['name' => 'Actualités']);
        $factory->post->create_many(5, ['post_category' => [self::$categorieParenteId]]);
    }

    public function test_les_articles_sont_rattaches_a_la_categorie(): void
    {
        $articles = get_posts(['category' => self::$categorieParenteId]);

        $this->assertCount(5, $articles);
    }
}
```

> L'essentiel à retenir : setUpBeforeClass et une méthode statique partagée évitent de recréer les mêmes objets ; Un trait dédié aux fixtures se réutilise dans plusieurs classes de test sans héritage lourd ; La mutualisation réduit aussi le temps d'exécution, pas seulement la duplication de code

## Partager entre plusieurs classes avec un trait

Pour aller plus loin, quand plusieurs classes de test distinctes ont besoin de la même arborescence de catégories, un trait dédié centralise la construction du jeu de fixtures, sans imposer une hiérarchie d'héritage entre les classes :

```
trait ArborescenceCategoriesFixture
{
    private static int $categorieParenteId;
    private static int $categorieEnfantId;

    public static function creerArborescenceCategories(WP_UnitTest_Factory $factory): void
    {
        self::$categorieParenteId = $factory->category->create(['name' => 'Actualités']);
        self::$categorieEnfantId = $factory->category->create([
            'name' => 'Locales',
            'parent' => self::$categorieParenteId,
        ]);
    }
}

class ArticlesParCategorieTest extends WP_UnitTestCase
{
    use ArborescenceCategoriesFixture;

    public static function wpSetUpBeforeClass(WP_UnitTest_Factory $factory): void
    {
        self::creerArborescenceCategories($factory);
    }
}
```

Six classes qui utilisaient chacune leur propre variante de cette arborescence ont pu adopter le même trait, ce qui a réduit la construction de données redondantes en base et rendu explicite, pour quiconque ouvre l'une de ces classes, que la structure de catégories provient d'une source commune documentée à un seul endroit.

## La précaution à ne pas oublier

Un jeu de fixtures partagé entre méthodes d'une même classe reste en lecture depuis toutes les méthodes qui suivent : une méthode de test qui modifierait ces objets partagés (renommer une catégorie, par exemple) affecterait silencieusement les méthodes suivantes de la classe. La règle à observer est simple : les fixtures partagées via `wpSetUpBeforeClass` ou un trait commun doivent rester strictement en lecture ; toute modification nécessaire à un test précis doit passer par une fixture créée localement dans ce test, pas par une modification du jeu partagé.

## En résumé

Remplacer un `setUp()` répété par un jeu de fixtures construit une seule fois, via `wpSetUpBeforeClass` et, au besoin, un trait partagé entre classes, réduit à la fois la duplication de code et le temps d'exécution d'une suite. La seule discipline à maintenir est de traiter ces fixtures partagées comme des données en lecture seule, jamais modifiées par un test individuel.
