# Un test passe en local et échoue en CI à cause d’un fuseau horaire

> « Failed asserting that two strings are identical » sur une simple date formatée : le coupable est presque toujours le fuseau horaire du serveur d'intégration continue.

- Auteur : WordPress Développement
- Publié le : 2022-06-26
- Mis à jour le : 2022-06-26
- Catégorie : Tests
- URL : https://www.wpmoderne.fr/tests/test-passe-local-echoue-ci-fuseau-horaire/

## L’essentiel

- Le serveur d'intégration continue tourne souvent en UTC par défaut
- Une date formatée localement diffère silencieusement de celle attendue
- Fixer explicitement le fuseau horaire élimine cette classe d'échecs

« Failed asserting that two strings are identical. --- Expected +++ Actual @@ -1 +1 @@ -'14:30' +'12:30' » : ce message d'échec, sur un test qui vérifie simplement l'heure affichée d'un article publié, laisse d'abord perplexe. En local, le même test passe sans le moindre problème, avec le même code, les mêmes données, la même version de PHP. La différence se situe ailleurs : dans le fuseau horaire du serveur qui exécute réellement le test.

Ce type d'écart entre environnement local et environnement d'intégration continue est l'un des plus déroutants à diagnostiquer, précisément parce que rien dans le code source du projet ne semble en cause. Le problème vient d'une configuration implicite, différente d'une machine à l'autre, que le test suppose à tort identique partout.

## Pourquoi les serveurs de CI tournent souvent en UTC

La majorité des images de conteneurs utilisées par les services d'intégration continue configurent PHP avec le fuseau horaire UTC par défaut, indépendamment de la localisation géographique de l'équipe qui développe le projet. Une machine de développement locale, en revanche, hérite généralement du fuseau horaire configuré au niveau du système d'exploitation, souvent celui de la zone géographique de l'équipe, par exemple Europe/Paris.

Un test qui formate une date sans jamais préciser explicitement de fuseau horaire dépend donc, sans le savoir, de ce réglage ambiant. Deux heures d'écart entre UTC et Europe/Paris en été suffisent à transformer une assertion parfaitement correcte en local en un échec systématique et reproductible sur le serveur d'intégration continue.

## Un exemple concret

> L'essentiel à retenir : Le serveur d'intégration continue tourne souvent en UTC par défaut ; Une date formatée localement diffère silencieusement de celle attendue ; Fixer explicitement le fuseau horaire élimine cette classe d'échecs

```
public function test_affiche_heure_de_publication(): void {
    $post_id = self::factory()->post->create( [
        'post_date' => '2022-06-26 14:30:00',
    ] );

    $heure_affichee = get_the_time( 'H:i', $post_id );

    $this->assertSame( '14:30', $heure_affichee );
}
```

Ce test suppose implicitement que `get_the_time` retourne l'heure telle qu'écrite dans `post_date`, sans conversion. En réalité, cette fonction applique le fuseau horaire configuré dans les réglages du site WordPress, via l'option `timezone_string` ou `gmt_offset`. Si cette option n'est pas explicitement définie dans l'environnement de test, WordPress retombe sur une valeur par défaut qui peut différer entre la machine locale et le serveur de CI.

## Isoler la cause avant de corriger

Avant de corriger à l'aveugle, il est utile de confirmer que le fuseau horaire est bien en cause, plutôt qu'un autre facteur d'environnement. Deux vérifications rapides suffisent généralement :

- Afficher la valeur de `date_default_timezone_get()` au début de la suite de tests, en local puis dans les journaux du serveur de CI, pour comparer directement les deux valeurs.
- Vérifier la valeur de l'option WordPress `timezone_string` dans le fichier de configuration de test, pour s'assurer qu'elle est bien fixée explicitement plutôt que laissée à sa valeur par défaut.

## Le correctif : fixer explicitement le fuseau horaire dans le bootstrap

```
// Dans le fichier bootstrap.php de la suite de tests
function fixe_le_fuseau_horaire_de_test() {
    update_option( 'timezone_string', 'Europe/Paris' );
}
tests_add_filter( 'muplugins_loaded', 'fixe_le_fuseau_horaire_de_test' );
```

Cette approche fixe une valeur unique et prévisible, identique quel que soit l'environnement d'exécution, ce qui élimine la dépendance implicite au réglage système de la machine hôte. Le test précédent devient alors fiable, puisque `get_the_time` applique systématiquement le même fuseau horaire, qu'il s'exécute en local ou sur le serveur d'intégration continue.

## Une alternative pour les calculs indépendants de WordPress

```
public function test_calcul_de_duree_independant_du_fuseau(): void {
    $debut = new DateTimeImmutable( '2022-06-26 14:30:00', new DateTimeZone( 'UTC' ) );
    $fin   = new DateTimeImmutable( '2022-06-26 16:00:00', new DateTimeZone( 'UTC' ) );

    $duree = $fin->diff( $debut )->h;

    $this->assertSame( 1, $duree );
}
```

Pour des calculs qui ne dépendent pas directement des réglages WordPress, préciser explicitement le fuseau horaire au niveau de chaque objet `DateTimeImmutable` manipulé dans le test rend ce test totalement indépendant de la configuration ambiante, qu'elle soit locale ou celle du serveur de CI.

> Un test qui manipule des dates ou des heures ne devrait jamais dépendre implicitement d'un réglage système ambiant : le fuseau horaire doit être fixé explicitement, soit au niveau de WordPress, soit au niveau des objets de date manipulés directement.

## Généraliser la vérification à toute la suite

Une fois la cause identifiée sur un test précis, il est utile de vérifier si d'autres tests de la suite reposent sur la même hypothèse implicite d'un fuseau horaire local. Une recherche du mot-clé `get_the_time`, `get_the_date` ou `current_time` dans l'ensemble de la suite de tests permet généralement de repérer rapidement les autres candidats susceptibles du même écart entre environnement local et environnement de CI.

## En résumé

Un test qui manipule une date ou une heure, et qui échoue uniquement sur le serveur d'intégration continue, pointe presque toujours vers un fuseau horaire implicite différent entre les deux environnements. Fixer explicitement ce réglage dans le fichier de bootstrap des tests, plutôt que de compter sur la configuration système ambiante, élimine cette source d'instabilité de façon définitive.
