Développement

PHPUnit et tests WordPress : guide pratique pour développeurs

Publié le 31 March 2026 — 6 min de lecture
En bref

Guide pratique PHPUnit et tests WordPress : installer la WP Test Suite, structurer les tests, mocking Brain Monkey et CI/CD avec GitHub Actions.

Introduction : pourquoi tester son code WordPress

Les tests automatisés sont l’assurance qualité du développeur. Sur WordPress, où chaque mise à jour peut briser des fonctionnalités, les tests PHPUnit permettent de détecter les régressions avant qu’elles n’atteignent la production. Pourtant, moins de 20 % des plugins WordPress publiés incluent une suite de tests. Ce guide vous montre comment mettre en place des tests efficaces : PHPUnit, WP Test Suite, Brain Monkey pour le mocking et une pipeline CI/CD avec GitHub Actions.

Installer PHPUnit et la WP Test Suite

# 1. Ajouter PHPUnit en dépendance de développement
composer require --dev phpunit/phpunit:^11.0

# 2. Installer WP-CLI (si pas encore installé)
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp

# 3. Créer la structure de tests via WP-CLI scaffold
wp scaffold plugin-tests mon-plugin

# Cela crée :
# bin/install-wp-tests.sh   (script d'installation WP Test Suite)
# phpunit.xml.dist           (config PHPUnit)
# tests/
#   bootstrap.php            (chargement WP dans les tests)
#   test-sample.php          (exemple de test)

# 4. Installer la WP Test Suite
bash bin/install-wp-tests.sh wordpress_test root '' localhost latest

Configuration phpunit.xml

<?xml version="1.0" encoding="UTF-8"?>
<phpunit
    bootstrap="tests/bootstrap.php"
    colors="true"
    verbose="true"
    stopOnFailure="false"
>
    <testsuites>
        <testsuite name="Mon Plugin">
            <directory>tests</directory>
        </testsuite>
    </testsuites>
    <coverage>
        <include>
            <directory suffix=".php">includes</directory>
        </include>
    </coverage>
</phpunit>

Structure d’un test PHPUnit : setUp, tearDown, assertions

<?php
use PHPUnitFrameworkTestCase;

class MonPluginServiceTest extends TestCase
{
    private MonPluginService $service;
    private array $testData;
    
    // Exécuté avant chaque test
    protected function setUp(): void
    {
        parent::setUp();
        $this->service = new MonPluginService();
        $this->testData = ['key' => 'value', 'count' => 42];
    }
    
    // Exécuté après chaque test
    protected function tearDown(): void
    {
        unset($this->service);
        parent::tearDown();
    }
    
    // Test : vérifier le traitement des données
    public function test_process_returns_expected_result(): void
    {
        $result = $this->service->process($this->testData);
        
        $this->assertIsArray($result);
        $this->assertArrayHasKey('processed', $result);
        $this->assertTrue($result['processed']);
        $this->assertEquals(42, $result['count']);
    }
    
    // Test avec exception attendue
    public function test_process_throws_exception_on_invalid_input(): void
    {
        $this->expectException(InvalidArgumentException::class);
        $this->expectExceptionMessage('Données invalides');
        
        $this->service->process([]);
    }
    
    // Test avec données multiples (data provider)
    /**
     * @dataProvider emailProvider
     */
    public function test_validate_email(string $email, bool $expected): void
    {
        $this->assertEquals($expected, $this->service->validateEmail($email));
    }
    
    public static function emailProvider(): array
    {
        return [
            ['test@example.com', true],
            ['invalid-email', false],
            ['test@.com', false],
            ['a@b.fr', true],
        ];
    }
}

Tester un plugin WordPress : hooks, filtres et fonctions

<?php
// Test avec WP_UnitTestCase (intégration WordPress)
class MonPluginWordPressTest extends WP_UnitTestCase
{
    // Créer des données de test avec les factories WP
    public function test_plugin_creates_custom_post_type(): void
    {
        // Créer un article de test
        $post_id = $this->factory()->post->create(array(
            'post_type'   => 'mon_cpt',
            'post_status' => 'publish',
            'post_title'  => 'Test Article',
        ));
        
        $this->assertIsInt($post_id);
        $this->assertGreaterThan(0, $post_id);
        
        $post = get_post($post_id);
        $this->assertEquals('mon_cpt', $post->post_type);
        $this->assertEquals('Test Article', $post->post_title);
    }
    
    // Tester les meta données
    public function test_save_post_meta(): void
    {
        $post_id = $this->factory()->post->create();
        
        // Simuler la sauvegarde du meta
        update_post_meta($post_id, '_ma_meta', 'valeur_test');
        
        $valeur = get_post_meta($post_id, '_ma_meta', true);
        $this->assertEquals('valeur_test', $valeur);
    }
    
    // Tester un filtre WordPress
    public function test_mon_filtre_modifie_contenu(): void
    {
        // Activer le filtre
        add_filter('the_content', 'mon_plugin_modifier_contenu');
        
        $contenu_original = 'Contenu original';
        $contenu_filtre = apply_filters('the_content', $contenu_original);
        
        $this->assertStringContainsString('Modifié', $contenu_filtre);
        
        // Nettoyer
        remove_filter('the_content', 'mon_plugin_modifier_contenu');
    }
}

Mocking avec Brain Monkey

<?php
use BrainMonkey;
use BrainMonkeyFunctions;

class MonServiceTest extends TestCase
{
    protected function setUp(): void
    {
        parent::setUp();
        MonkeysetUp();
    }
    
    protected function tearDown(): void
    {
        Monkey	earDown();
        parent::tearDown();
    }
    
    public function test_service_utilise_get_option(): void
    {
        // Mocker la fonction WordPress get_option
        Functionsexpect('get_option')
            ->once()
            ->with('mon_plugin_option')
            ->andReturn('valeur_mockee');
        
        Functionsexpect('sanitize_text_field')
            ->once()
            ->andReturnFirstArg();
        
        $service = new MonService();
        $resultat = $service->getOption();
        
        $this->assertEquals('valeur_mockee', $resultat);
    }
    
    public function test_hooks_sont_enregistres(): void
    {
        // Vérifier qu'un hook est bien ajouté
        Functionsexpect('add_action')
            ->once()
            ->with('init', Mockery::type('callable'));
        
        $plugin = new MonPlugin();
        $plugin->init();
    }
}

Tests d’intégration vs unitaires

Type Vitesse Isolation Base de données Usage
Unitaire (Brain Monkey) Très rapide Totale Non Logique métier pure
Intégration (WP_UnitTestCase) Lent Partielle Oui (SQLite/MySQL) Fonctions WordPress
Fonctionnel (Codeception) Très lent Aucune Oui Scénarios utilisateur

CI/CD avec GitHub Actions

# .github/workflows/tests.yml
name: Tests PHPUnit WordPress

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        php-version: ['8.1', '8.2', '8.3']
        wordpress-version: ['latest', '6.6']
    
    services:
      mysql:
        image: mysql:8.0
        env:
          MYSQL_ROOT_PASSWORD: root
          MYSQL_DATABASE: wordpress_test
        options: --health-cmd="mysqladmin ping" --health-interval=10s
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: ${{ matrix.php-version }}
          extensions: mysqli, dom, libxml, mbstring
          coverage: xdebug
      
      - name: Install Composer dependencies
        run: composer install --prefer-dist --no-progress
      
      - name: Install WordPress test suite
        run: bash bin/install-wp-tests.sh wordpress_test root root localhost ${{ matrix.wordpress-version }}
      
      - name: Run PHPUnit tests
        run: vendor/bin/phpunit --coverage-clover=coverage.xml
      
      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v3
        with:
          file: coverage.xml

Pour des développements WordPress professionnels avec tests et CI/CD, notre développeur WordPress Paris peut auditer et renforcer votre codebase.

Questions fréquentes sur PHPUnit et les tests WordPress

Combien de temps faut-il pour mettre en place des tests sur un plugin existant ?

Pour un plugin existant sans tests, comptez 2 à 5 jours pour mettre en place l’infrastructure (PHPUnit, WP Test Suite, CI/CD) et écrire les premiers tests sur les fonctions critiques. Le retour sur investissement est rapide : chaque régression évitée en production vaut plusieurs heures de débogage. Commencez par les fonctions les plus utilisées et les plus risquées (traitement de formulaires, requêtes BDD, calculs).

Quelle est la couverture de code (code coverage) idéale ?

Il n’existe pas de chiffre universel, mais 80 % est souvent cité comme objectif raisonnable. Plus important que le pourcentage global : couvrir les chemins critiques (paiements, sauvegarde de données, authentification) à 100 %, et les utilitaires à 70-80 %. Une couverture de 100 % n’est pas toujours réaliste ni souhaitable : certains cas d’erreur système sont impossibles à déclencher en test.

Brain Monkey ou WP_UnitTestCase : lequel utiliser ?

Les deux sont complémentaires. Brain Monkey est idéal pour les tests unitaires purs : rapide, pas besoin de base de données, parfait pour tester la logique métier isolée. WP_UnitTestCase est nécessaire pour les tests d’intégration impliquant de vraies fonctions WordPress (WP_Query, options, posts). Une bonne suite de tests utilise les deux : Brain Monkey pour 70-80 % des tests (rapides) et WP_UnitTestCase pour les 20-30 % restants.

Peut-on tester WooCommerce avec PHPUnit ?

Oui. WooCommerce fournit ses propres factories de tests (WC_Helper_Product, WC_Helper_Order) disponibles via le package woocommerce/woocommerce. Vous pouvez créer des produits et commandes de test, simuler le tunnel d’achat et tester vos personnalisations WooCommerce. La configuration nécessite d’installer le package WooCommerce en mode test et de bootstrapper WooCommerce dans votre tests/bootstrap.php.

W
Rédigé par
WebEngine
Développeur web freelance à Paris spécialisé WordPress, WooCommerce et SEO technique depuis 2010. 13 avis vérifiés · Note 5/5. Chaque site livré atteint un score PageSpeed mobile supérieur à 90.

Un projet en tête ?

Devis gratuit sous 48h, sans engagement.

Demander un devis gratuit