# Tester un raccourci [shortcode] personnalisé sans lancer WordPress

> Isoler la logique d'un shortcode dans une fonction pure permet de la tester en quelques millisecondes, sans charger le cœur de WordPress ni sa base de données.

- Auteur : WordPress Développement
- Publié le : 2023-04-27
- Mis à jour le : 2023-04-27
- Catégorie : Tests
- URL : https://www.wpmoderne.fr/tests/tester-shortcode-personnalise-sans-wordpress/

## L’essentiel

- Séparer le rendu du shortcode de la logique de calcul le rend testable seul
- Un test unitaire sur une fonction pure s'exécute sans WP_UnitTestCase
- Le callback enregistré par add_shortcode reste une simple façade fine

Pourquoi un test qui vérifie la sortie d'un shortcode devrait-il charger une base de données MySQL, initialiser l'ensemble des hooks du cœur et instancier l'objet `$wp_query` ? La réponse habituelle — « parce que `WP_UnitTestCase` est l'outil disponible » — n'est pas satisfaisante quand le shortcode en question ne fait rien d'autre que transformer des attributs en une chaîne de caractères.

La solution consiste à extraire la logique du shortcode dans une fonction pure, indépendante de l'environnement WordPress, et à ne réserver l'appel à `add_shortcode()` qu'à une fine couche d'intégration testée séparément, une seule fois.

## Le piège du callback monolithique

La forme la plus courante d'un shortcode mélange trois responsabilités dans une seule fonction : lire les attributs, appliquer une logique métier (calcul, mise en forme, appel à une donnée), et produire le balisage HTML final. Tant que ces trois responsabilités restent imbriquées, tester le calcul oblige à passer par le rendu complet, donc par WordPress :

```
// Version monolithique, difficile à tester isolément
add_shortcode('compte_a_rebours', function (array $atts): string {
    $atts = shortcode_atts(['date' => ''], $atts);
    $cible = new DateTimeImmutable($atts['date']);
    $jours = $cible->diff(new DateTimeImmutable())->days;

    return sprintf('<span class="compte-a-rebours">%d jour(s)</span>', $jours);
});
```

## Extraire la logique en fonction pure

La même fonctionnalité, découpée, sépare le calcul du rendu :

```
// Fonction pure, testable sans WordPress
function calculer_jours_restants(string $dateCible, DateTimeImmutable $maintenant): int
{
    $cible = new DateTimeImmutable($dateCible);

    return $maintenant->diff($cible)->days;
}

// Façade fine, appelée par add_shortcode
add_shortcode('compte_a_rebours', function (array $atts): string {
    $atts = shortcode_atts(['date' => ''], $atts);
    $jours = calculer_jours_restants($atts['date'], new DateTimeImmutable());

    return sprintf('<span class="compte-a-rebours">%d jour(s)</span>', $jours);
});
```

> L'essentiel à retenir : Séparer le rendu du shortcode de la logique de calcul le rend testable seul ; Un test unitaire sur une fonction pure s'exécute sans WP_UnitTestCase ; Le callback enregistré par add_shortcode reste une simple façade fine

La fonction `calculer_jours_restants()` ne dépend d'aucune fonction du cœur WordPress : elle peut être testée avec un simple `PHPUnit\Framework\TestCase`, sans étendre `WP_UnitTestCase` ni charger de base de données.

## Le test unitaire correspondant

```
use PHPUnit\Framework\TestCase;

final class CompteARebourseTest extends TestCase
{
    public function test_calcule_le_bon_nombre_de_jours(): void
    {
        $maintenant = new DateTimeImmutable('2024-01-01');

        $jours = calculer_jours_restants('2024-01-10', $maintenant);

        $this->assertSame(9, $jours);
    }

    public function test_renvoie_zero_pour_une_date_passee(): void
    {
        $maintenant = new DateTimeImmutable('2024-01-15');

        $jours = calculer_jours_restants('2024-01-01', $maintenant);

        $this->assertSame(0, $jours);
    }
}
```

Ce test s'exécute en quelques millisecondes, sans dépendance externe, et peut tourner dans une étape de CI distincte de la suite d'intégration, ce qui permet de le lancer à chaque sauvegarde de fichier pendant le développement.

## Ce qui mérite encore un test d'intégration

Extraire la logique métier ne dispense pas totalement de `WP_UnitTestCase` : il reste utile de vérifier, au moins une fois, que le shortcode est bien enregistré et que `do_shortcode('[compte_a_rebours date="2024-12-25"]')` produit un balisage cohérent avec les attributs par défaut de `shortcode_atts()`. Ce test d'intégration reste court, car il ne vérifie que le branchement, pas le calcul lui-même, déjà couvert par les tests unitaires purs.

### Répartir les responsabilités entre les deux suites

- Tests unitaires purs : toutes les variantes de calcul, y compris les cas limites (date invalide, date déjà passée, fuseau horaire).
- Test d'intégration WordPress : un seul cas nominal, pour vérifier l'enregistrement du shortcode et l'échappement correct du HTML produit.

## En résumé

Découper un shortcode en une fonction pure et une façade d'enregistrement permet de tester l'essentiel de sa logique sans jamais démarrer l'environnement WordPress. Le gain en vitesse d'exécution encourage à multiplier les cas limites testés, ce qu'un test d'intégration lourd décourage naturellement par sa durée.
