De janvier 2022 à avril 2024, j'ai exercé en tant que Développeur PHP au sein du groupe Le Monde, où j'ai eu l'opportunité de développer et maintenir des applications web stratégiques, notamment le tunnel d'abonnement des sites du groupe (Le Monde, Courrier International, Le Monde Diplomatique, Le Nouvel Obs et Telerama).
Au cours de cette période, dans un objectif constant de recherche de qualité, j'avais suggéré aux équipes de mettre en place le Test Driven Development dans nos pratiques de développement.
L'amélioration de la qualité technique d'une plateforme aussi vaste que celle du Monde nécessitait une refonte du système de tests existant. Le projet utilisait initialement Codeception, mais cette approche présentait plusieurs inconvénients, notamment un couplage fort avec l'environnement et des difficultés à maintenir une séparation claire entre les tests unitaires et les tests fonctionnels.
Les défis de l'ère Codeception
J'ai rapidement identifié un problème fondamental : Un manque d'isolation des tests unitaires qui causaient des lenteurs (il fallait attendre vingt-cing minutes pour que la suite de tests s'éxécute entièrement), et des crashs aléatoires de la pipeline d'Intégration Continue en local :
Parfois les tests Cypress ne s'exécutaient pas jusqu'au bout, le terminal était "freeze" et il fallait exécuter à nouveau tous les tests depuis le début.
J'ai toujours défendu l'idée que les tests unitaires doivent valider la plus petite unité de logique possible. Par définition, cela signifie qu'ils ne devraient pas utiliser les services d'injection de dépendance (DI) du framework, ni RabbitMQ, ni la base de données, ni charger des seeds. À la place, ils doivent absolument utiliser des mocks pour simuler les dépendances.
Cependant, dans l'ancienne configuration, les tests Codeception rencontraient des exceptions PDO imprévues liées à la base de données (pour une raison inconnue). Pour résoudre des problèmes de connexion persistants, il était parfois nécessaire de fermer explicitement les connexions PDO dans la méthode _after()
des tests Codeception qui interagissaient avec la base de données.
De plus, le processus de intégration continue, géré via Travis, affichait les résultats des tests des quatre environnements, (Le Monde, NouvelObs, Diplo et Telerama) ce qui rendait le chargement de la page impossible ou faisait crasher le navigateur.
La migration vers PHPUnit : un gage de qualité
Afin de gagner en clarté et en robustesse, j'ai convaincu les équipes d'entreprendre une refactorisation en profondeur pour migrer la suite de tests de Codeception vers PHPUnit.
Les objectifs étaient clairs :
- Gagner du temps en permettant l'exécution indépendante de la suite de tests unitaires et fonctionnels.
- Permettre une exécution complète et fiable des tests (PHPUnit ne cause pas d'exceptions PDO).
- Découpler le code de Phalcon (le framework sous-jacent) de la suite de tests unitaires.
- Migrer vers un standard plus maintenable.
Ce travail a impliqué :
Clarification des responsabilités: Dans le but de mieux organiser notre suite de tests, j'ai proposé le déplacement des tests fonctionnels vers un dossier approprié (et de renommer leurs namespaces). Lorsque ceux-ci utilisaient le service d'injection de dépendances de Phalcon, RabbitMQ ou la base de données.
Utilisation accrue des Mocks: Lorsqu'il était possible de les refactoriser, j'ai encouragé l'utilisation de mocks dans les tests fonctionnels qui pouvaient être convertis en tests purement unitaires. (Par exemple pour simuler les résultats des repositories et éviter les appels directs en base de données.)
Amélioration de la CI: En déplaçant les tests fonctionnels hors du scope des tests unitaires, les équipes ont pu itérer plus rapidement dans la mesure où il était devenu possible de gagner du temps en exécutant uniquement la suite de tests unitaires (d'une durée de quelques minutes seulement).
Aussi, j'ai ajouté le paramètre--stop-on-failure
à la commande PHPUnit dans leMakefile
pour améliorer la lisibilité des logs.
Le résultat de cette refactorisation est un environnement de développement où les tests unitaires sont plus fiables et rapides, et où l'intégration continue est plus stable, nous permettant de nous concentrer sur la production de code de qualité, tout en respectant l'objectif d'améliorer notre vélocité.
Nous nous sommes débarrassés de Codeception au profit d'une structure de tests plus conventionnelle et performante basée sur PHPUnit.
Top comments (0)