assertEquals('12', 12) retourne vrai dans PHPUnit, sans le moindre avertissement. Cette comparaison souple, qui applique les règles de conversion de type de PHP avant de comparer deux valeurs, explique un cas de test resté vert malgré un bug réel, rencontré sur une extension qui calcule le nombre de places disponibles pour un atelier de médiation numérique en bibliothèque.
La fonction censée retourner un entier représentant le nombre de places restantes retournait, à la suite d’une refactorisation, une chaîne de caractères issue d’un appel à get_post_meta() jamais converti en entier. Le test existant, écrit avec assertEquals, n’a rien détecté : la valeur numérique était correcte, seul son type avait changé.
Symptôme : un test vert, un bug bien réel
Le bug s’est révélé non pas par un échec de test, mais par un comportement inattendu côté interface : un composant JavaScript qui comparait strictement cette valeur à 0 avec l’opérateur === ne détectait plus jamais l’épuisement des places, puisque la chaîne "0" n’est jamais strictement égale à l’entier 0 en JavaScript non plus. Le test PHP, lui, restait silencieusement vert.
Diagnostic : la comparaison souple en cause

Le test original comparait la valeur retournée à un entier attendu, en utilisant assertEquals, qui applique en interne les mêmes règles de comparaison souple que l’opérateur == de PHP :
// Le test original, resté vert malgré le bug
public function ilRetourneLeNombreDePlacesRestantes(): void
{
update_post_meta($this->atelier_id, 'places_restantes', '0');
$resultat = wpm_places_restantes($this->atelier_id);
$this->assertEquals(0, $resultat); // vrai, que $resultat soit 0 ou "0"
}
Le résultat réel de la fonction, une fois le bug introduit, était la chaîne "0". assertEquals(0, "0") retourne vrai, car PHP convertit implicitement la chaîne en entier avant de comparer, exactement comme le ferait l’opérateur ==.
Correctif : remplacer assertEquals par assertSame
assertSame compare à la fois la valeur et le type, sans aucune conversion implicite, de la même façon que l’opérateur === de PHP :
public function ilRetourneLeNombreDePlacesRestantesCommeEntier(): void
{
update_post_meta($this->atelier_id, 'places_restantes', '0');
$resultat = wpm_places_restantes($this->atelier_id);
$this->assertSame(0, $resultat); // échoue si $resultat est la chaîne "0"
}
Avec ce changement, le test échoue immédiatement dès que la fonction retourne une chaîne au lieu d’un entier, révélant le bug avant même qu’il n’atteigne un environnement de production.
Corriger également la fonction, pas seulement le test
La correction complète a nécessité un cast explicite dans la fonction elle-même, puisque get_post_meta() retourne systématiquement une chaîne de caractères par défaut dans WordPress, indépendamment du type de la valeur stockée à l’origine :
function wpm_places_restantes(int $atelier_id): int
{
return (int) get_post_meta($atelier_id, 'places_restantes', true);
}
Prévention : quand préférer assertSame par défaut
- Pour toute valeur dont le type est significatif pour l’appelant, notamment un entier, un booléen ou un objet précis,
assertSamedevrait constituer le choix par défaut. assertEqualsgarde son utilité pour comparer des objets porteurs de logique d’égalité personnalisée, ou des valeurs dont seule l’équivalence numérique importe réellement.- Une revue de code peut signaler systématiquement tout
assertEqualscomparant un entier littéral à une valeur retournée par une fonction, comme point de vigilance à vérifier au cas par cas.
Une comparaison souple pardonne un bug de type ; une comparaison stricte le signale immédiatement, au moment où il coûte le moins cher à corriger.
En résumé
assertEquals a laissé passer un bug de type qui a changé le comportement réel d’une fonction sans jamais faire échouer le test censé la couvrir. Remplacer cette assertion par assertSame, plus stricte, a suffi à révéler l’écart entre une chaîne et un entier numériquement identiques, un cas fréquent dès qu’une valeur transite par les métadonnées WordPress sans conversion de type explicite.