# declare(strict_types=1) dans vos tests PHPUnit WordPress

> Le cœur de WordPress reste en typage faible, mais rien n'empêche vos fichiers de test d'activer le typage strict. Voici ce que cela change concrètement.

- Auteur : Clément Hadrot
- Publié le : 2023-07-23
- Mis à jour le : 2023-07-23
- Catégorie : Tests
- URL : https://wpmoderne.dev.wordpress-developpement.fr/tests/strict-types-tests-phpunit-wordpress/

## L’essentiel

- strict_types s'active fichier par fichier, jamais globalement
- Un mock qui retourne un mauvais type devient une erreur immédiate
- WordPress lui-même reste en typage faible, source de frictions ponctuelles

Une équipe rejoignant un projet existant s'est étonnée qu'un mock configuré pour retourner `'42'` (une chaîne) au lieu de `42` (un entier) n'ait jamais fait échouer aucun test, alors que le code appelant supposait manifestement recevoir un entier pour effectuer un calcul. Le typage faible de PHP, combiné à l'absence de `declare(strict_types=1)` dans les fichiers de test, laissait passer cette incohérence sans le moindre avertissement — la coercition automatique transformait silencieusement la chaîne en nombre au moment du calcul, masquant l'erreur de configuration du mock.

Activer le typage strict dans les fichiers de test, indépendamment de ce que fait le reste du projet, est une décision locale et réversible qui mérite d'être comprise avant d'être appliquée partout sans discernement.

## Ce que fait réellement strict_types

Contrairement à une idée reçue, `declare(strict_types=1)` ne rend pas tout le projet strictement typé : cette directive s'applique uniquement aux appels de fonctions effectués depuis le fichier qui la déclare, pour les arguments qui portent une déclaration de type scalaire. Sans elle, PHP convertit silencieusement les types compatibles (une chaîne numérique vers un entier, par exemple) ; avec elle, un type incompatible passé en argument déclare typé lève une `TypeError` immédiate.

## L'effet sur les mocks et les assertions

Dans un fichier de test avec `strict_types` activé, une méthode de mock configurée avec un type de retour incohérent par rapport à la signature de l'interface qu'elle simule échoue dès l'appel, plutôt que de laisser filer une valeur silencieusement convertie plus loin dans la chaîne d'appels :

```
<?php
declare(strict_types=1);

interface Service_Tarification {
    public function calculerRemise(int $quantite): float;
}

class Test_Panier extends \PHPUnit\Framework\TestCase {

    public function test_remise_appliquee_correctement(): void {
        $service = $this->createMock(Service_Tarification::class);
        $service->method('calculerRemise')->willReturn(0.15);

        $panier = new Panier($service);
        $total = $panier->calculerTotal(100.0, 8);

        $this->assertEquals(85.0, $total);
    }
}
```

> L'essentiel à retenir : strict_types s'active fichier par fichier, jamais globalement ; Un mock qui retourne un mauvais type devient une erreur immédiate ; WordPress lui-même reste en typage faible, source de frictions ponctuelles

Sans `strict_types`, un appel accidentel avec une quantité passée sous forme de chaîne `'8'` plutôt que l'entier `8` aurait été silencieusement converti et le test aurait continué à passer, masquant une erreur de type qui aurait pu se propager ailleurs dans un contexte moins tolérant.

## La friction avec un cœur WordPress non strict

WordPress lui-même n'utilise pas `strict_types` dans son cœur, et de nombreuses fonctions natives acceptent ou retournent des types avec une certaine souplesse historique — `get_option()` peut retourner `false` là où un code strict attendrait un type précis, `get_post_meta()` retourne systématiquement une chaîne même pour une valeur stockée comme un entier. Un fichier de test avec `strict_types` activé qui appelle directement ces fonctions natives doit donc caster explicitement leurs retours avant de les passer à du code lui-même strictement typé :

```
$quota = (int) get_post_meta($id, 'quota_restant', true);
$service->verifierQuota($quota);
```

Cette friction n'est pas un défaut de `strict_types` : elle révèle simplement, de façon explicite, un cast qui existait déjà implicitement, mais silencieusement, avant son activation.

## Faut-il l'activer sur tous les fichiers de test ?

- Sur des classes de test unitaires purement PHP, sans dépendance à des fonctions natives WordPress à typage souple, l'activation ne coûte rien et sécurise immédiatement les appels entre mocks et code testé.
- Sur des classes `WP_UnitTestCase` qui interagissent beaucoup avec l'API WordPress, l'activation demande plus de rigueur sur les casts explicites, sans bénéfice toujours proportionnel à l'effort.
- Un projet neuf peut raisonnablement l'activer partout dès le départ ; un projet existant volumineux gagne à l'introduire progressivement, fichier par fichier, en commençant par les tests unitaires purs déjà découplés de WordPress.

> Le typage strict dans les tests ne corrige rien tout seul : il transforme une incohérence silencieuse en une erreur immédiate et explicite, au moment même où elle se produit plutôt que trois appels de fonction plus loin.

## Ce sujet ne couvre pas

Cette discussion porte sur l'effet de `strict_types` au moment de l'exécution des tests. L'analyse statique via PHPStan ou Psalm, qui détecte des incohérences de type avant même l'exécution du code, répond à un besoin complémentaire mais distinct, déjà traité par ailleurs — les deux approches se renforcent mutuellement sans se substituer l'une à l'autre.

## Notre verdict

Sur les classes de test unitaires découplées de WordPress — celles qui testent une logique métier pure — activer `declare(strict_types=1)` est une décision à faible coût et à bénéfice immédiat. Sur les classes d'intégration profondément couplées à l'API WordPress, le gain existe mais demande d'accepter une gymnastique de casts explicites qui ne convainc pas toujours toute une équipe du premier coup.
