La documentation officielle de Symfony est claire sur ce point : « le composant PHPUnit Bridge fournit des utilitaires pour faciliter les tests avec PHPUnit ». Rien, en revanche, n’y est dit sur la cohabitation avec le cycle de chargement de WordPress, une situation pourtant courante dès qu’un projet mélange composants Symfony, comme HttpFoundation ou Console, et cœur WordPress.
Deux options existent : garder WP_UnitTestCase comme base et ajouter les composants Symfony par-dessus, ou faire tourner PHPUnit via le paquet symfony/phpunit-bridge, qui apporte son propre lot d’outils. Ce billet compare les deux approches sur un projet réellement hybride. Codeception, qui répond à une problématique différente d’organisation des tests d’acceptation, n’est pas traité ici.
Ce qu’apporte réellement PHPUnit Bridge
Le paquet symfony/phpunit-bridge n’est pas un remplaçant de PHPUnit : c’est une surcouche qui ajoute principalement deux choses utiles, un système de détection des dépréciations PHP et Symfony, et un mécanisme de gestion de version de PHPUnit indépendant de celle installée globalement.
Sur un projet hybride, cette détection des dépréciations est précieuse : elle signale, sans faire échouer le build par défaut, chaque appel à une méthode Symfony marquée comme obsolète, ce qui anticipe les montées de version majeures du framework.
Ce que WP_UnitTestCase apporte de son côté
De l’autre côté, WP_UnitTestCase reste la seule base qui initialise correctement l’environnement WordPress : base de données de test réinitialisée entre chaque test, factories pour les articles et les utilisateurs, hooks remis à zéro. Aucun de ces mécanismes n’existe nativement dans PHPUnit Bridge.

Faire cohabiter les deux dans une seule suite
Dans la pratique, la solution la plus stable consiste à garder WP_UnitTestCase comme classe mère pour tous les tests qui touchent au cœur WordPress, et à réserver les composants Symfony testés isolément dans des classes qui étendent directement PHPUnit\Framework\TestCase, sans bootstrap WordPress.
| Critère | WP_UnitTestCase seul | Ajout de PHPUnit Bridge |
|---|---|---|
| Réinitialisation base de données | Automatique | Absente, à gérer soi-même |
| Détection des dépréciations Symfony | Absente | Intégrée |
| Compatibilité factories WordPress | Native | Nécessite un bootstrap combiné |
| Isolation du conteneur de services | Manuelle | Facilitée par les composants Symfony |
Un bootstrap combiné, la solution la plus courante
La plupart des projets hybrides finissent par écrire un fichier bootstrap.php qui charge d’abord l’environnement WordPress classique, puis initialise le conteneur de services Symfony par-dessus, avant de lancer PHPUnit avec la configuration standard.
require_once dirname( __DIR__ ) . '/vendor/autoload.php';
require_once getenv( 'WP_TESTS_DIR' ) . '/includes/functions.php';
tests_add_filter( 'muplugins_loaded', function () {
require dirname( __DIR__ ) . '/mon-plugin.php';
} );
require getenv( 'WP_TESTS_DIR' ) . '/includes/bootstrap.php';
Quand choisir PHPUnit Bridge malgré tout
Si le composant Symfony testé n’a aucune dépendance au cycle de vie WordPress, par exemple un service de validation de formulaire pur, il est parfaitement raisonnable de le tester dans une classe séparée, plus rapide à exécuter puisqu’elle évite tout le bootstrap WordPress.
- Service purement Symfony, sans hook ni base de données WordPress : classe de test légère, sans
WP_UnitTestCase - Logique liée aux articles, options ou utilisateurs WordPress : rester sur
WP_UnitTestCase - Détection de dépréciation utile sur toute la suite : ajouter PHPUnit Bridge en complément, pas en remplacement
Sur nos projets hybrides, la règle qui a le mieux fonctionné : un seul runner PHPUnit, deux familles de classes de test selon ce qu’elles touchent réellement.
Notre verdict
Opposer PHPUnit Bridge et WP_UnitTestCase n’a pas vraiment de sens : ce sont deux outils complémentaires, pas deux runners concurrents. Le premier apporte une vigilance sur les dépréciations Symfony, le second reste indispensable dès que le test touche au cœur WordPress. Faire tourner deux runners distincts pour un seul projet, en revanche, complique la maintenance sans bénéfice réel.