paint-brush
Configuration d'un environnement de bout en bout parfaitement isolépar@marcinwosinek
473 lectures
473 lectures

Configuration d'un environnement de bout en bout parfaitement isolé

par Marcin Wosinek5m2023/04/12
Read on Terminal Reader

Trop long; Pour lire

Les tests floconneux sont des tests qui échouent pour des raisons sans rapport avec votre code. Dans les cas extrêmes, des tests floconneux apprendront à votre équipe à ignorer les résultats E2E. Cela peut tuer l'effort d'automatisation du contrôle qualité (QA). L'approche présentée ici aborde deux grandes sources de problèmes potentiels dans vos tests.
featured image - Configuration d'un environnement de bout en bout parfaitement isolé
Marcin Wosinek HackerNoon profile picture

Pour des tests stables de bout en bout (E2E), nous avons besoin d'un environnement aussi isolé que possible de l'extérieur.

Réduire la desquamation

Les tests floconneux sont des tests qui échouent pour des raisons sans rapport avec votre code. Ils rendent difficile l'utilisation d'E2E comme vérification fiable de l'exactitude de l'application. Dans les cas extrêmes, des tests floconneux apprendront à votre équipe à ignorer les résultats E2E. Cela peut tuer l'effort d'automatisation du contrôle qualité (QA).


L'approche présentée ici aborde deux grandes sources de problèmes potentiels dans vos exécutions de test :


  • État stocké par le backend partagé par différentes tâches de test, et


  • Services externes sur lesquels vous n'avez aucun contrôle.


Il existe d'autres sources de flakiness non affectées par cette approche :


  • Le vrai problème est dans l'application qui est apparue au hasard, ou


  • Les problèmes dans l'application sont causés par la vitesse anormale à laquelle E2E interagit avec elle.

Alternative

Avant que mon équipe et moi n'effectuions mes tests sur un conteneur backend dédié, nous utilisions l'un de nos serveurs hors production. Cette approche convenait parfaitement au stade de l'expérimentation de notre solution E2E.


Lorsqu'il n'y avait que quelques tests, nous ne pouvions de toute façon pas utiliser les résultats des tests pour prendre des décisions.


Cependant, alors que nous continuions à ajouter plus de tests et à générer des temps d'exécution plus longs, cette approche a commencé à s'effondrer. Les principaux enjeux étaient les suivants :


  • Même si nous avons essayé d'annuler les modifications de données dans le test, certains échecs de test laissaient derrière eux des changements inattendus.


  • Les emplois parallèles s'entrechoquaient. Différentes tâches de test changeaient les mêmes états, ce qui provoquait souvent l'échec de l'une des tâches.

Dockeriser tout

Une solution à ce problème consistait à dédier un serveur principal et une base de données distincts pour chaque travail de test. Cette approche serait très difficile sans Docker.


Les conteneurs Docker sont un outil parfait pour créer un environnement confiné avec tout ce dont une application a besoin pour fonctionner :


  • Le bon système d'exploitation (ou plutôt la bonne distribution Linux),


  • les dépendances du système, telles que les bibliothèques de manipulation d'images, etc., et


  • La version correcte des interpréteurs de langage (Python, Node, etc.) ou des serveurs de base de données.

Base de données

Pour votre test, vous pouvez préparer un conteneur de base de données dédié fourni avec des données de test prévisibles. De cette manière, vous pourrez reproduire exactement le point de départ de chaque exécution E2E, ce qui rendra vos tests plus stables.


Vous pouvez utiliser différentes balises pour votre image Docker, pour la gestion des versions de la base de données de test. La même base de données de test peut également être utilisée dans un environnement de développement. Pour les tests manuels en développement, vous avez besoin d'exemples d'entités similaires à ceux des tests automatisés.

Backend

Si vous avez déjà utilisé Docker pour déployer votre backend, il sera assez facile de réutiliser la même image pour exécuter votre E2E. Dans mon équipe, nous déployons un backend sous forme de conteneurs et nous fournissons des URL de base de données et des informations d'identification sous forme de variables d'environnement.


La même version de conteneur peut être déployée en production ou utilisée en intégration continue (CI) pour exécuter des tests. Chaque environnement fournit les bonnes valeurs pour se connecter à la base de données.

L'extrémité avant

En fonction de votre stratégie de déploiement, vous pouvez effectuer l'une des opérations suivantes :


  1. Utilisez les conteneurs que vous créez dans le cadre de la version frontale.


  2. Obtenez les fichiers compilés et assurez-vous qu'ils sont disponibles via HTTP pour les tests.


Dans notre cas, nous utilisons l'option 2 : nous déployons l'application sous forme de fichiers statiques, nous venons donc de créer un conteneur dédié pour servir les fichiers construits lors des exécutions de tâches E2E.

Services d'emploi dans GitLab

Nous utilisons GitLab comme plate-forme pour exécuter notre CI. Chaque travail dans GitLab est exécuté dans un conteneur avec une image de votre choix. En plus du conteneur principal, vous pouvez définir des services : Des conteneurs supplémentaires s'exécutant parallèlement à vos tests. La configuration est aussi simple que :

 <job-name>: services: - name: <image> alias: <container-url>


Les options disponibles sont similaires à celles que vous avez dans Docker Compose, mais elles sont plus limitées.

Un "gotcha" dans la configuration GitLab consiste à définir la variable FF_NETWORK_PER_BUILD sur 1 si vous souhaitez autoriser les services à s'accéder pendant l'exécution du test.

Considérez les données ad hoc pour l'isolement en cours d'emploi

À un moment donné, nous exécutions tous les tests en parallèle dans un seul travail. À cette époque, il était nécessaire d'appliquer une isolation encore plus forte : chaque test utilisait le même backend et la même base de données.


Pour contourner ce problème, nous avons mis à jour nos tests pour qu'ils dépendent principalement des données aléatoires que nous injectons juste dans la section before des tests. Cela permettait aux tests de s'exécuter sans être affectés par d'autres modifications se produisant dans d'autres threads.


Cette approche peut être un peu délicate au début, mais elle peut avoir du sens selon votre situation.

Nettoyer après chaque test

Même si nous commençons une nouvelle base de données pour chaque tâche de test, nous essayons toujours de faire en sorte que nos tests laissent l'application dans le même état qu'ils l'ont trouvée. C'est peut-être un peu un vestige de la période où nous faisions des tests dans un environnement partagé.


Ce n'est plus crucial, mais cela peut toujours aider lors du développement des tests dans les cas suivants :


  • Lorsque vous n'exécutez qu'un seul test, l'état rencontré par le test n'est donc pas différent de celui que vous rencontrez lorsque vous exécutez tous les tests du fichier.


  • Lorsque vous réexécutez le même test localement encore et encore, afin que la base de données ne soit pas affectée par les exécutions précédentes

Faux service externe

Il existe des cas où le déplacement de services vers un conteneur n'est pas une option. Par exemple:


  • S'il existe des serveurs externes que l'application utilise directement ou via un proxy backend, ou


  • Vous possédez des serveurs qui ne peuvent pas être exécutés à l'intérieur d'un conteneur en raison de problèmes techniques.


Dans les deux cas, pour isoler les exécutions de test, vous pouvez vous moquer des requêtes adressées à ces services. Cela empêchera les services externes imprévisibles d'affecter vos résultats de test. Un inconvénient de cette approche est que vos tests se déconnecteront du contexte dans lequel vos applications fonctionnent.


Avec des simulations en place, vos tests ne détectent pas les cas où des modifications de ces services affectent votre application.

Continuez à apprendre

Si vous souhaitez en savoir plus sur les tests ou d'autres sujets liés à la programmation, vous pouvez vous inscrire ici pour recevoir des mises à jour lorsque je publie du contenu connexe.