vendredi 25 septembre 2026

À propos

Contact

Tests

Data providers PHPUnit pour couvrir les variantes de WP_Query

Douze requêtes similaires, douze méthodes de test presque identiques ? Un fournisseur de données unique permet de tout couvrir sans dupliquer une ligne.

Par Clément Hadrot • 12 septembre 2020 • 4 min de lecture • Aucun commentaire
Data providers PHPUnit pour couvrir les variantes de WP_Query

Une extension d’annuaire professionnel que nous maintenons propose un filtrage par catégorie, par ville et par statut d’adhésion. Combinés, ces trois filtres produisent des dizaines de variantes de WP_Query à vérifier : catégorie seule, ville seule, les deux ensemble, avec ou sans adhérent actif, etc. La première version de la suite comptait quatorze méthodes de test, presque toutes identiques à trois lignes près. Un fournisseur de données a permis de tout ramener à une seule méthode.

Le data provider PHPUnit répond exactement à ce besoin : dérouler un même scénario de test sur un ensemble de jeux de données, sans dupliquer la logique d’assertion.

Étape 1 — Identifier le squelette de test répété

Avant d’écrire le provider, il faut repérer ce qui varie réellement entre les méthodes existantes. Dans notre cas : les arguments passés à WP_Query, et le nombre de résultats attendus. Le reste — création des fixtures, appel à la requête, assertion sur le compte — était strictement identique.

public function test_filtre_categorie_seule(): void {
    $requete = new WP_Query(['post_type' => 'membre', 'tax_query' => [...]]);
    $this->assertCount(3, $requete->posts);
}

public function test_filtre_ville_seule(): void {
    $requete = new WP_Query(['post_type' => 'membre', 'meta_query' => [...]]);
    $this->assertCount(5, $requete->posts);
}

Étape 2 — Écrire le fournisseur de données

Un data provider est une méthode qui retourne un tableau de tableaux, chaque sous-tableau correspondant aux arguments d’un appel de la méthode de test. Depuis PHPUnit 9, on peut aussi utiliser des clés textuelles pour nommer chaque cas dans le rapport :

public static function scenarios_filtrage(): array {
    return [
        'categorie seule'            => ['args' => ['tax_query' => [['taxonomy' => 'secteur', 'terms' => 'photographie']]], 'attendu' => 3],
        'ville seule'                => ['args' => ['meta_query' => [['key' => 'ville', 'value' => 'Lyon']]], 'attendu' => 5],
        'categorie et ville'         => ['args' => ['tax_query' => [['taxonomy' => 'secteur', 'terms' => 'photographie']], 'meta_query' => [['key' => 'ville', 'value' => 'Lyon']]], 'attendu' => 1],
        'aucun filtre'               => ['args' => [], 'attendu' => 9],
        'ville inexistante'          => ['args' => ['meta_query' => [['key' => 'ville', 'value' => 'Atlantide']]], 'attendu' => 0],
    ];
}

Étape 3 — Brancher le provider sur la méthode de test

Depuis PHPUnit 10, l’attribut #[DataProvider] remplace l’annotation @dataProvider historique, mais les deux syntaxes cohabitent selon la version du projet :

#[DataProvider('scenarios_filtrage')]
public function test_filtrage_annuaire(array $args, int $attendu): void {
    $requete = new WP_Query(array_merge(['post_type' => 'membre'], $args));
    $this->assertCount($attendu, $requete->posts);
}
L'essentiel à retenir : Un tableau de scénarios, une seule méthode de test ; Nommer chaque cas pour un rapport lisible ; Combiner plusieurs providers pour multiplier les axes

Chaque entrée du tableau devient une exécution indépendante de test_filtrage_annuaire, avec son propre statut dans le rapport — un échec sur « ville et categorie » n’affecte pas les quatre autres cas, et le rapport nomme précisément lequel a échoué.

Étape 4 — Préparer les fixtures une seule fois

Le provider ne doit fournir que des données statiques (arguments et résultats attendus), jamais créer de contenu en base — il est exécuté avant même l’initialisation de WordPress dans certains contextes. Les fixtures correspondantes se créent donc classiquement dans setUp(), de façon à couvrir tous les cas du provider avec un seul jeu de données cohérent :

protected function setUp(): void {
    parent::setUp();
    $this->factory()->post->create(['post_type' => 'membre', 'meta_input' => ['ville' => 'Lyon']]);
    // ... création des huit autres membres avec combinaisons ville/catégorie/statut
}

Combiner plusieurs providers pour multiplier les axes

Quand deux dimensions indépendantes doivent être croisées — par exemple le filtrage et le rôle de l’utilisateur qui exécute la requête — il est tentant d’ajouter un second #[DataProvider]. PHPUnit ne les combine pas automatiquement en produit cartésien : il faut le faire soi-même dans un seul provider, ou accepter deux méthodes de test distinctes si la logique diffère réellement selon le rôle :

  • Un provider unique reste préférable tant que la logique testée est identique quel que soit l’axe.
  • Deux providers séparés se justifient si les assertions elles-mêmes diffèrent selon l’axe testé.
  • Un tableau généré dynamiquement (boucle imbriquée dans le provider) évite d’écrire à la main un produit cartésien de dix lignes.

Un data provider bien nommé documente à lui seul les règles métier du filtrage — nul besoin d’aller lire le code de l’extension pour comprendre ce qu’elle est censée faire.

En résumé

Les data providers ne réduisent pas seulement la duplication : ils rendent explicite la matrice de scénarios qu’un développeur doit avoir en tête en modifiant la logique de filtrage. Sur l’annuaire professionnel, faire passer quatorze méthodes à une seule a aussi eu un effet secondaire appréciable — ajouter un nouveau scénario de filtrage ne demande plus qu’une ligne dans le tableau, jamais une nouvelle méthode complète à écrire et maintenir.

Partager :

À propos de l'auteur

Clément Hadrot

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi