PHPUnit est le framework de test unitaire de référence pour PHP. Développé par Sebastian Bergmann, il est utilisé par la quasi-totalité des projets PHP sérieux, de Symfony à Laravel. Maîtriser PHPUnit est indispensable pour tout développeur souhaitant écrire du code fiable, maintenable et testable. Voir la documentation officielle PHPUnit pour la référence complète.
Installation avec Composer
L'installation se fait via Composer en dépendance de développement :
composer require --dev phpunit/phpunit ^11
Créez ensuite un fichier phpunit.xml à la racine du projet :
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php" colors="true">
<testsuites>
<testsuite name="Application Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>
Écrire votre premier test
Un test PHPUnit est une classe qui étend PHPUnit\Framework\TestCase. Chaque méthode préfixée par test est exécutée automatiquement :
use PHPUnit\Framework\TestCase;
class CalculatorTest extends TestCase
{
public function testAdditionReturnsCorrectResult(): void
{
$calc = new Calculator();
$this->assertEquals(5, $calc->add(2, 3));
}
public function testDivisionByZeroThrowsException(): void
{
$this->expectException(\InvalidArgumentException::class);
(new Calculator())->divide(10, 0);
}
}
Assertions essentielles
PHPUnit fournit des dizaines d'assertions couvrant tous les cas de figure courants :
assertEquals($expected, $actual)— égalité de valeurassertSame($expected, $actual)— égalité stricte (type et valeur)assertTrue($condition)/assertFalse($condition)assertInstanceOf($class, $object)— vérification de typeassertCount($count, $array)— taille d'un tableauassertStringContainsString($needle, $haystack)— sous-chaîne présente
Data Providers
Les data providers permettent d'exécuter le même test phpunit avec plusieurs jeux de données différents :
/** @dataProvider additionProvider */
public function testAdd(int $a, int $b, int $expected): void
{
$this->assertEquals($expected, (new Calculator())->add($a, $b));
}
public static function additionProvider(): array
{
return [[0, 0, 0], [1, 2, 3], [-1, 1, 0], [100, 200, 300]];
}
Mocks et stubs
Les mocks permettent d'isoler le code testé en remplaçant ses dépendances par des objets simulés :
public function testUserServiceSendsEmail(): void
{
$mailer = $this->createMock(MailerInterface::class);
$mailer->expects($this->once())
->method('send')
->with($this->stringContains('@example.com'));
(new UserService($mailer))->register('user@example.com');
}
Couverture de code
Pour générer un rapport de couverture, installez Xdebug puis lancez :
./vendor/bin/phpunit --coverage-html coverage/
Visez une couverture de 80% minimum sur le code critique. Une couverture à 100% n'est pas toujours nécessaire ni rentable sur les couches de présentation ou les getters simples.
TDD : Test-Driven Development
Le cycle TDD est Red → Green → Refactor : écrire le test qui échoue, écrire le minimum de code pour le passer, puis refactoriser. Cette discipline force à concevoir des interfaces claires et du code découplé dès le départ.
Conclusion
PHPUnit est bien plus qu'un outil de test : c'est un levier de qualité pour tout projet PHP. En combinant des tests unitaires bien structurés, des data providers pour les cas limites, et des mocks pour l'isolation des dépendances, vous bâtissez un filet de sécurité qui rend chaque refactorisation sereine. Commencez par tester vos services métier critiques, puis étendez progressivement la couverture. Intégrez PHPUnit dans votre pipeline CI/CD avec GitHub Actions pour une validation automatique à chaque commit. Les tests ne sont pas une contrainte : ils sont un investissement qui réduit drastiquement le coût des bugs en production.
Intégration continue avec PHPUnit
Automatisez l'exécution de vos tests PHPUnit dans un pipeline CI/CD : chaque commit déclenche la suite de tests, et tout échec bloque le déploiement. Cette discipline garantit qu'aucune régression n'atteint la production. Configurez des seuils de couverture minimaux (--min-coverage-lines 80) pour maintenir la qualité du code dans le temps.
Annotations et attributs PHP 8
PHPUnit 10+ préfère les attributs PHP 8 aux annotations PHPDoc. Remplacez @dataProvider par #[DataProvider('method')], @test est optionnel si la méthode commence par test, et #[Group('slow')] remplace @group slow. Cette évolution améliore la performance (pas de parsing de PHPDoc) et le support des IDEs. Migrez progressivement vos tests existants vers la nouvelle syntaxe PHP 8 lors de chaque refactorisation.