Introduction : pourquoi vos tests mentent et vous les croyez
\n\nImaginez : vous avez écrit 50 tests unitaires, couvert tous les if-else, passé en CI — tout est vert. Une semaine plus tard, la production plante avec l'erreur "Division by zero". Comment ? Puisque les tests passaient ! Cela vous dit quelque chose ?
Le problème des tests unitaires classiques (approximatifs, avec des nombres spécifiques) est qu'ils vérifient ce que vous savez déjà. Vous choisissez des arguments qui, selon vous, mèneront à une erreur. Mais l'esprit du programmeur est prévisible : nous écrivons tous testDivideByZero et oublions testDivideByNegativeZero ou testDivideByVeryLargeFloat.
C'est là qu'intervient le test basé sur les propriétés en PHP — une méthode qui ne vérifie pas des scénarios spécifiques, mais prouve les propriétés de votre code pour des milliers de données d'entrée aléatoires. Aujourd'hui, nous allons voir comment intégrer cette approche dans votre projet PHP en utilisant Eris et PHPUnit. Vous apprendrez à trouver des bugs que les tests ordinaires laissent passer, et pourquoi ce n'est pas de la magie, mais de l'ingénierie.
\n\nQu'est-ce que le test basé sur les propriétés ? (et pourquoi ce n'est pas aléatoire)
\n\nUn test unitaire classique ressemble à ceci : assert(2 + 2 === 4). Vous vérifiez une seule affirmation spécifique. Le test basé sur les propriétés (PBT) fonctionne différemment : vous formulez une propriété — une affirmation qui doit être vraie pour toutes les données d'entrée valides.
Exemple de propriété pour une fonction d'addition :
\n- \n
- Commutativité :
a + b === b + apour tous les nombres. \n - Idempotence : l'application répétée de la fonction ne change pas le résultat. \n
- Invariance : le résultat est toujours positif (si c'est la propriété). \n
Le PBT génère des centaines de valeurs aléatoires (y compris des valeurs limites, nulles, négatives, NaN) et vérifie si la propriété n'est pas violée. Si un contre-exemple est trouvé — le test échoue avec les données d'entrée spécifiques qui ont causé l'erreur. Vous n'obtenez pas simplement "le test a échoué", mais un bug reproductible.
\n\nEn PHP, cette technique est particulièrement utile en raison du typage dynamique : vous ne savez jamais quel type arrivera réellement dans une fonction.
\n\nOutils pour le test basé sur les propriétés en PHP
\n\nL'outil principal est la bibliothèque Eris (github.com/giorgiosironi/eris). Elle s'intègre avec PHPUnit et fournit des générateurs de données aléatoires. L'alternative — les capacités intégrées de PHPUnit 10+ (mais elles sont encore immatures). Nous utiliserons Eris, car c'est un outil mature et documenté.
\n\nInstallation via Composer :
\ncomposer require --dev giorgiosironi/eris\n\nFaker sera également utile pour générer des structures complexes (email, noms, adresses).
\n\ncomposer require --dev fakerphp/faker\n\nÉcrire notre premier test basé sur les propriétés : casser le tri
\n\nSupposons que nous ayons une fonction sortArray() qui utilise quicksort. Écrivons une propriété : "le tableau après le tri ne doit pas contenir d'élément plus petit que le précédent".
use Eris\\TestTrait;\nuse Eris\\Generator\\IntegerGenerator;\nuse PHPUnit\\Framework\\TestCase;\n\nclass SortTest extends TestCase\n{\n use TestTrait;\n\n public function testSortedArrayProperty(): void\n {\n $this->forAll(\n Generator\\seq(Generator\\int())\n )->then(function (array $input) {\n $sorted = sortArray($input);\n for ($i = 0; $i < count($sorted) - 1; $i++) {\n $this->assertLessThanOrEqual(\n $sorted[$i + 1],\n $sorted[$i],\n "Le tableau n'est pas trié : " . json_encode($sorted)\n );\n }\n });\n }\n}\n\n\nExécution