Écrire des assertions PHPUnit plus simples grâce au VarDumper
Les tests unitaires sont une étape cruciale pour garantir la qualité de votre
code, mais parfois, les répétitions peuvent devenir lassantes. Avez-vous déjà soupiré en enchaînant des appels à $this->assertXXX()
pour valider des structures complexes ? Heureusement, il existe une solution élégante pour simplifier tout cela : le composant Symfony/VarDumper.
Voyons ensemble comment l’utiliser pour rendre vos tests plus concis et lisibles tout en conservant leur efficacité.
Section intitulée un-exemple-concretUn exemple concret
Imaginons que nous souhaitions tester certaines propriétés d’une classe comme celle-ci :
final readonly class MyObject
{
public function __construct(
public string $aPublicProperty = 'a public property',
protected string $aProtectedProperty = 'a protected property',
private string $aPrivateProperty = 'a private property',
public string $anotherPublicProperty = 'another public property',
protected string $anotherProtectedProperty = 'another protected property',
private string $anotherPrivateProperty = 'another private property',
) {}
}
Lorsque vous dumpez un objet instancié avec ses valeurs par défaut, voici le résultat obtenu :
PhpunitVarDumper\MyObject^ {#325
+aPublicProperty: "a public property"
#aProtectedProperty: "a protected property"
-aPrivateProperty: "a private property"
+anotherPublicProperty: "another public property"
#anotherProtectedProperty: "another protected property"
-anotherPrivateProperty: "another private property"
}
Section intitulée simplifier-les-testsSimplifier les tests
Traditionnellement, on utiliserait plusieurs appels à $this->assertSame()
pour valider ces propriétés. Cependant, grâce à Symfony/VarDumper, nous pouvons alléger ce processus en utilisant une assertion sur le dump directement.
Commencez par installer le composant en mode développement :
composer require --dev symfony/var-dumper
Ensuite, importez le trait VarDumperTestTrait
et utilisez la méthode assertDumpEquals()
dans vos tests :
use PHPUnit\Framework\TestCase;
use PhpunitVarDumper\MyObject;
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
final class MyObjectTest extends TestCase
{
use VarDumperTestTrait;
public function test()
{
$myObject = new MyObject();
$this->assertDumpEquals(
<<<'DUMP'
PhpunitVarDumper\MyObject {
+aPublicProperty: "a public property"
#aProtectedProperty: "a protected property"
-aPrivateProperty: "a private property"
+anotherPublicProperty: "another public property"
#anotherProtectedProperty: "another protected property"
-anotherPrivateProperty: "another private property"
}
DUMP,
$myObject,
);
}
}
N’est-ce pas plus clair et élégant ? 🎉
Section intitulée aller-plus-loin-avec-les-castersAller plus loin avec les Casters
Dans certains cas, toutes les propriétés d’un objet ne sont pas pertinentes pour vos tests, ou vous ne souhaitez pas les mettre à jour à chaque modification de la classe. C’est ici que les casters entrent en jeu.
Un caster est une fonction de rappel qui personnalise la représentation d’un objet dumpé. Elle prend en paramètre :
- L’objet en cours de dump ;
- Un tableau représentant l’état de l’objet ;
- (d’autres paramètres que nous n’utilisons pas ici).
Pour ajouter un caster, utilisez la méthode setUpVarDumper()
dans votre test :
final class MyObjectTest extends TestCase
{
use VarDumperTestTrait;
protected function setUp(): void
{
$this->setUpVarDumper(
[
MyObject::class => static function (MyObject $myObject, array $a): array {
return $a;
},
],
);
}
}
Pour le moment, notre caster ne sert à rien. Observons donc ce que contient la variable $a
:
^ array:6 [
"aPublicProperty" => "a public property"
"\x00*\x00aProtectedProperty" => "a protected property"
"\x00PhpunitVarDumper\MyObject\x00aPrivateProperty" => "a private property"
"anotherPublicProperty" => "another public property"
"\x00*\x00anotherProtectedProperty" => "another protected property"
"\x00PhpunitVarDumper\MyObject\x00anotherPrivateProperty" => "another private property"
]
Si vous avez déjà joué avec PHP et ses mécanismes de sérialisation, vous ne devriez pas être perdu. Sinon une petite explication s’impose :
- Chaque clé représente une propriété de l’objet.
- Les notations varient en fonction de la visibilité de la propriété :
- Pour une propriété publique, son nom apparaît directement en clair, comme
"aPublicProperty"
. - Pour une propriété protégée, son nom est précédé par le préfixe spécial
\x00*\x00
, qui signale sa visibilité restreinte. - Pour une propriété privée, le préfixe indique son contexte de déclaration :
\x00[NomDeLaClasse]\x00
. Ici, cela donne par exemple\x00PhpunitVarDumper\MyObject\x00aPrivateProperty
.
- Pour une propriété publique, son nom apparaît directement en clair, comme
Ces notations un peu cryptiques peuvent sembler complexes à première vue. Heureusement, Symfony fournit des constantes pour les manipuler plus facilement, comme Caster::PREFIX_PROTECTED
ou Caster::PATTERN_PRIVATE
. Utilisons-les pour simplifier notre code de caster :
use Symfony\Component\VarDumper\Caster\Caster;
protected function setUp(): void
{
$this->setUpVarDumper(
[
MyObject::class => static function (MyObject $myObject, array $a) {
unset(
$a['anotherPublicProperty'],
$a[Caster::PREFIX_PROTECTED.'anotherProtectedProperty'],
$a[sprintf(Caster::PATTERN_PRIVATE, MyObject::class, 'anotherPrivateProperty')],
);
return $a;
},
],
AbstractDumper::DUMP_LIGHT_ARRAY,
);
}
Ce caster permet de supprimer les propriétés non pertinentes. Le test devient alors :
public function test()
{
$myObject = new MyObject();
$this->assertDumpEquals(
<<<'DUMP'
PhpunitVarDumper\MyObject {
+aPublicProperty: "a public property"
#aProtectedProperty: "a protected property"
-aPrivateProperty: "a private property"
}
DUMP,
$myObject,
);
}
En cas d’erreur, PHPUnit affiche un diff très lisible, ce qui facilite le debug :
1) PhpunitVarDumper\Tests\MyObjectTest::test
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
'PhpunitVarDumper\MyObject {
- +aPublicProperty: "Hello you!"
+ +aPublicProperty: "a public property"
#aProtectedProperty: "a protected property"
-aPrivateProperty: "a private property"
}'
Section intitulée quelques-astuces-supplementairesQuelques astuces supplémentaires
- Affichage léger des tableaux Utilisez
AbstractDumper::DUMP_LIGHT_ARRAY
comme deuxième paramètre desetUpVarDumper()
pour des tableaux plus compacts.-array:3 [ - 0 => "a" - 1 => "b" - 2 => "c" +[ + "a" + "b" + "c" ]
- Gestion des valeurs dynamiques Préférez un caster à
assertDumpMatchesFormat()
, car les diff générés avec des formats sont souvent difficiles à lire.
Section intitulée conclusionConclusion
Le composant VarDumper est un allié précieux, tant pour le débogage que pour simplifier vos tests. Grâce à lui, vous gagnez en clarté et en efficacité.
Alors, dites adieu aux assertions fastidieuses, et concentrez-vous sur ce qui compte vraiment : la qualité de votre code. 🎉
Commentaires et discussions
Nos formations sur ce sujet
Notre expertise est aussi disponible sous forme de formations professionnelles !

Symfony avancée
Découvrez les fonctionnalités et concepts avancés de Symfony
Ces clients ont profité de notre expertise
La société AramisAuto a fait appel à JoliCode pour développer au forfait leur plateforme B2B. L’objectif était de développer une nouvelle offre à destination des professionnels ; déjà testé commercialement, pro.aramisauto.com est la concrétisation de 3 mois de développement. Le service est indépendant de l’infrastructure existante grâce à la mise en…
Afin de poursuivre son déploiement sur le Web, Arte a souhaité être accompagné dans le développement de son API REST “OPA” (API destinée à exposer les programmes et le catalogue vidéo de la chaine). En collaboration avec l’équipe technique Arte, JoliCode a mené un travail spécifique à l’amélioration des performances et de la fiabilité de l’API. Ces…
Dans le cadre d’une refonte complète de son architecture Web, le journal en ligne Mediapart a sollicité l’expertise de JoliCode afin d’accompagner ses équipes. Mediapart.fr est un des rares journaux 100% en ligne qui n’appartient qu’à ses lecteurs qui amène un fort traffic authentifiés et donc difficilement cachable. Pour effectuer cette migration, …