# Tests unitaires écrits par un assistant IA : notre audit de 200 tests

> Nous avons fait relire 200 tests PHPUnit générés par un assistant de code sur trois projets WordPress. Faux positifs, assertions vides, couverture réelle : le bilan chiffré.

- Auteur : Clément Hadrot
- Publié le : 2025-11-07
- Mis à jour le : 2025-11-07
- Catégorie : Tests
- URL : https://wpmoderne.dev.wordpress-developpement.fr/tests/audit-tests-unitaires-generes-ia/

## L’essentiel

- Un tiers des tests générés ne vérifiait en réalité presque rien
- Les assertions sur des mocks entièrement fabriqués passent inaperçues à la relecture rapide
- Le gain de temps existe, mais seulement avec une revue humaine systématique

Deux cents tests PHPUnit générés en une soirée, sur trois extensions WordPress différentes, par un assistant de code auquel on avait simplement demandé de « couvrir les fonctions non testées » de chaque projet. Le chiffre de couverture affiché par l'outil de mesure a bondi de façon spectaculaire dès le lendemain matin. La question qu'on s'est posée ensuite était plus intéressante que le chiffre lui-même : est-ce que ces tests protègent vraiment contre des régressions, ou est-ce qu'ils gonflent artificiellement une métrique sans vérifier grand-chose de réel ?

On a fait relire méthodiquement l'intégralité des 200 tests par deux développeurs seniors, indépendamment l'un de l'autre, avec une grille de lecture simple : le test échouerait-il si on cassait volontairement le comportement qu'il est censé vérifier ? Le résultat de cet audit est resté suffisamment instructif pour être partagé ici, chiffres à l'appui.

## Le chiffre qui a surpris toute l'équipe

Sur les 200 tests audités, 68 se sont révélés incapables de détecter une régression volontairement introduite dans le code testé, soit un peu plus d'un tiers de l'ensemble. La cause n'était presque jamais une erreur de syntaxe visible : le test s'exécutait bien, passait au vert, et affichait une assertion qui semblait raisonnable à première lecture. Le problème se situait plus profondément, dans ce que l'assertion vérifiait réellement.

## Le piège le plus fréquent : tester le mock plutôt que le code

Sur près de la moitié des tests défaillants, le test avait créé un mock complet de la dépendance testée, puis vérifiait que ce mock se comportait comme configuré, sans jamais réellement solliciter le code de production visé :

```
// Test généré, apparemment valide, qui ne teste en réalité que le mock lui-même
public function test_calcul_frais_livraison() {
    $service = $this->createMock( Service_Livraison::class );
    $service->method( 'calculer_frais' )->willReturn( 4.90 );

    $this->assertEquals( 4.90, $service->calculer_frais( 'FR', 2.5 ) );
}
```

Ce test ne peut jamais échouer, quelle que soit la modification apportée au vrai `Service_Livraison`, puisqu'il n'appelle jamais son code réel : il vérifie seulement que le mock répond ce qu'on lui a demandé de répondre. Le corriger a demandé, dans chaque cas, de réintroduire une instance réelle de la classe testée, en ne mockant que ses dépendances externes véritables, comme un appel à une API de transporteur.

> L'essentiel à retenir : Un tiers des tests générés ne vérifiait en réalité presque rien ; Les assertions sur des mocks entièrement fabriqués passent inaperçues à la relecture rapide ; Le gain de temps existe, mais seulement avec une revue humaine systématique

## Le deuxième piège : des assertions trop larges ou vides de sens

Une autre catégorie récurrente, environ un quart des tests défaillants : des assertions génériques comme `assertNotNull()` ou `assertIsArray()` appliquées au résultat d'une fonction complexe, sans jamais vérifier la valeur réelle attendue. Ce type d'assertion détecte effectivement une erreur fatale ou un type de retour radicalement faux, mais laisse passer sans broncher une valeur de calcul erronée, tant qu'elle reste du bon type :

```
// Insuffisant : détecte seulement un crash, pas une valeur fausse
$resultat = calculer_total_panier( $panier );
$this->assertIsFloat( $resultat );

// Ce que la revue humaine a substitué
$resultat = calculer_total_panier( $panier );
$this->assertEqualsWithDelta( 127.45, $resultat, 0.01 );
```

## Ce que l'assistant a fait correctement, sans mérite à minimiser

Il serait malhonnête de réduire ce bilan à ses seuls défauts. Sur les cas simples, fonctions pures avec entrées et sorties clairement délimitées, validation de formats de données, calculs sans dépendance externe, les tests générés étaient corrects, bien structurés, et couvraient souvent des cas limites que l'équipe elle-même aurait pu négliger sous la pression du calendrier, comme une chaîne vide ou une valeur négative inattendue en entrée d'une fonction de calcul de remise.

- Cas limites bien couverts : environ 80 % des tests sur fonctions pures incluaient au moins un cas limite pertinent
- Lisibilité : les noms de méthodes de test générés étaient globalement clairs et descriptifs
- Temps gagné sur la rédaction initiale : estimé à environ 60 % par rapport à une rédaction entièrement manuelle des mêmes cas

## La règle qu'on applique désormais systématiquement

Depuis cet audit, aucun test généré n'est intégré au dépôt sans être d'abord volontairement mis en échec : on modifie temporairement et légèrement le code testé pour introduire une régression délibérée, on vérifie que le test échoue bien en conséquence, puis on annule la modification. Cette étape, qui prend quelques minutes par test, aurait à elle seule éliminé la totalité des 68 tests défaillants identifiés lors de l'audit initial.

> Un test qui passe toujours, quoi que fasse le code qu'il est censé vérifier, ne mesure rien : il rassure sans protéger, ce qui est plus dangereux qu'une couverture de tests honnêtement incomplète.

## Notre verdict

Un assistant de code peut accélérer significativement la rédaction de tests unitaires, en particulier sur des fonctions pures et des cas limites que l'équipe néglige parfois, mais il ne remplace en rien la vérification qu'un test échoue effectivement quand le comportement testé change réellement. La couverture de code affichée par un outil de mesure ne dit rien de la qualité des assertions sous-jacentes : sur ce point précis, notre audit confirme qu'un chiffre de couverture qui grimpe soudainement mérite une relecture humaine avant d'être présenté comme un progrès réel de fiabilité.
