Aller au contenu principal

Introduction à Cypress

Démarrez avec Cypress pour vos tests fonctionnels. Ce guide complet couvre l'installation, l'exécution des tests dans des containers Docker, la synchronisation de vos fichiers de tests et la capture de screenshots en cas d'erreur.

· 9 minutes de lecture
Voir la source
Christophe
Amoureux de Markdown, WSL et Docker ~ Curieux insatiable.
Cet article existe aussi en anglais — lire la version originale.

Traduction automatique

Cette traduction a été produite par une IA. Elle peut contenir des contresens ou des maladresses, en particulier sur les termes techniques. En cas de doute, consultez l'article de référence en anglais — c'est lui qui fait foi.

Journal des modifications

Dernière
Updated Cypress from 12.17.4→15.19.0 in package.json and cypress/included:14.2.0→15.19.0 in Dockerfiles.

Introduction à Cypress

⚡
TL;DR

Ce guide propose une introduction pas à pas à Cypress pour automatiser vos tests fonctionnels front-end. Vous allez apprendre à créer un nouveau projet Cypress, écrire vos premiers tests et les exécuter dans un container Docker. Le tutoriel couvre les workflows de développement essentiels : comment synchroniser vos fichiers de tests locaux avec le container pour un retour rapide et comment configurer Docker pour récupérer automatiquement les screenshots d'erreur du container vers votre machine hôte, afin de déboguer facilement.

Vous avez créé un site web pour vous-même ou pour un client : comment être sûr qu'il fonctionne toujours ? OK, à l'époque où vous travailliez dessus, tout marchait ; le formulaire de recherche, le formulaire de contact, les différents liens étaient tous fonctionnels. Mais comment en être sûr dans le temps ? Ne serait-il pas utile de disposer d'une procédure permettant de lancer plusieurs tests dits « fonctionnels » pour vérifier que tout marche encore ? Cela pourrait faire partie du contrat de maintenance que vous proposez à votre client.

Quel outil utiliser pour ce type de besoin ?

Les tests fonctionnels répondent à la question « le site fonctionne-t-il toujours ? » ; les tests unitaires répondent à « cette fonction fonctionne-t-elle toujours ? ». Pour ces derniers, voyez Écrire des tests unitaires PHP avec Pest et Linux - Scripts Bash - Lancer des tests unitaires avec bats/bats.

Cypress est un outil de test front-end qui permet aux développeurs d'automatiser des tests fonctionnels directement dans le navigateur. Il permet de naviguer entre les pages, d'interagir avec les éléments, de soumettre des formulaires et de vérifier le contenu ou les changements d'URL, ce qui simplifie les tests end-to-end et d'intégration.

En juin 2024, j'ai écrit un article sur un outil de tests fonctionnels PHP appelé Behat ; voyons maintenant comment procéder avec Cypress, qui est un outil JavaScript.

Attention, spoiler

Cypress est vraiment facile à utiliser et écrire des tests est plutôt direct. Contrairement à Behat, qui demande beaucoup plus de compétences et de travail de mise en place, Cypress se prend en main rapidement ; le dépannage est largement simplifié grâce aux screenshots pris dès qu'une erreur survient et Cypress se charge d'attendre le chargement complet d'une page, contrairement à Behat.

Une poignée de fichiers, un docker build, un docker run, et voici le résultat :

Première exécution

Information

À ce stade, vous avez copié quelques fichiers, construit une image Docker, lancé Cypress dans un container et obtenu un message All specs passed!.

Si on prend quelques secondes pour y réfléchir, nous avons déjà créé un premier test fonctionnel : s'assurer que notre site est en ligne et que le contenu HTML contient un ensemble de mots que nous nous attendons à y trouver. Si notre site est généré par un CMS, par exemple, le simple fait que le test passe prouve déjà que toute la partie base de données et PHP a parfaitement fonctionné. Un petit test pour nous, un grand pas pour notre confiance envers notre hébergeur.

Créons quelques fichiers et lançons un premier test​

Créez un répertoire temporaire :

>user@machine: ~/yourproject

$ mkdir -p /tmp/cypress && cd $_

Créez le fichier package.json avec le contenu suivant. L'objectif est d'indiquer que nous avons besoin de la dépendance cypress et de définir deux commandes, open et run.

{
"name": "cypress_sandbox",
"version": "1.0.0",
"description": "Playing with cypress",
"scripts": {
"cypress:open": "cypress open",
"cypress:run": "cypress run"
},
"devDependencies": {
"cypress": "^15.19.0"
}
}

Ce fichier package.json définit une configuration de projet Node.js appelé cypress_sandbox. Il déclare deux scripts npm pour lancer Cypress en mode interactif ou en mode exécution automatisée, et spécifie Cypress comme dépendance de développement.

Nous avons aussi besoin d'un fichier de configuration, qui doit s'appeler cypress.config.js. Créez ce fichier avec le contenu ci-dessous.

En résumé, nous définissons l'URL de notre moteur Cypress local à http://localhost:3100, nous remplaçons le port par défaut 3000 par 3100 et nous précisons que nous n'utilisons pas de fichier de configuration de support Cypress.

const { defineConfig } = require('cypress');
module.exports = defineConfig({
e2e: {
baseUrl: 'http://localhost:3100',
port: 3100,
supportFile: false,
},
});

Ce fichier configure Cypress, un framework de test automatisé pour les applications web. Il exporte une configuration qui indique à Cypress de tester l'application en cours d'exécution sur localhost:3100 et de désactiver le fichier de support par défaut.

Créons un premier test tout bête : nous allons visiter mon blog et vérifier que, quelque part, mon nom complet apparaît :

describe('Testing my blog', () => {
it('Check my last name is somewhere', () => {
cy.visit('https://www.avonture.be')
cy.contains('Christophe Avonture')
})
})

Ce code définit un test automatisé avec Cypress qui visite un site web et vérifie qu'un nom spécifique apparaît sur la page. C'est un test de fumée basique pour s'assurer que le contenu attendu est présent.

Un fichier optionnel à créer est .dockerignore : il indique à Docker de ne pas copier certains fichiers dans notre image Docker. Dans ce tutoriel, nous n'en avons pas vraiment besoin, mais c'est toujours une bonne idée d'avoir ce fichier comme pense-bête : Docker peut ignorer des fichiers lors de la copie des fichiers et répertoires pendant la construction d'une image.

node_modules
Dockerfile
.dockerignore

Ce fichier .gitignore liste les répertoires et fichiers à exclure du contrôle de version Git. Il ignore node_modules (dépendances npm), le Dockerfile (configuration de conteneur), et .dockerignore (fichier de configuration Docker), ce qui évite de commiter des fichiers volumineux ou spécifiques à l'environnement.

Enfin, dernier fichier à créer : notre propre image Docker.

FROM cypress/included:15.19.0
WORKDIR /app
COPY --chown=node:node package*.json ./
RUN npm install
COPY --chown=node:node cypress/ ./cypress/
COPY --chown=node:node cypress.config.js ./
RUN npx cypress verify
USER node
CMD ["npx", "cypress", "run", "--browser", "chrome"]

Ce Dockerfile construit une image Docker pour exécuter des tests Cypress. Il part d'une image de base qui inclut déjà Cypress, installe les dépendances npm du projet, copie la configuration et les tests Cypress, vérifie que Cypress fonctionne correctement, puis configure le conteneur pour lancer les tests dans Chrome au démarrage.

Si nous regardons notre projet actuel dans VSCode, cela ressemble à ceci :

Notre projet Cypress dans VSCode

Pour créer notre image et lancer Cypress, ouvrez une console et lancez cette commande : clear ; docker build -t cypress-test . && docker run --rm cypress-test.

Si tout se passe bien, vous obtiendrez la même sortie que celle déjà montrée en haut de cet article.

Synchroniser les fichiers entre notre host et le container​

Bien, ajoutons un nouveau test mais, d'abord, une question : devons-nous reconstruire notre image Docker encore et encore ? Certainement pas ! Si nous ne devons pas modifier le Dockerfile ou des réglages, ce n'est pas nécessaire.

Mais, jusqu'ici, dans notre Dockerfile, nous avons utilisé des instructions COPY pour placer nos tests directement dans l'image Docker. Ce n'est pas un problème du tout ; il suffit de dire à Docker d'ignorer ces fichiers et d'utiliser ceux de notre host.

C'est simple.

D'abord, créons un deuxième test :

describe('Navigation Test', () => {
it('should navigate to the tags page', () => {
cy.visit('https://www.avonture.be');
cy.contains('a', 'Tags').click();
cy.url().should('include', '/tags');
cy.get('h1').should('contain', 'Tags');
});
});

Ce test automatisé vérifie que la navigation vers la page Tags fonctionne correctement. Il visite le site, clique sur le lien Tags, puis confirme que l'URL et le titre de la page ont changé comme prévu.

En résumé, nous voulons aller sur la page d'accueil puis cliquer sur l'élément de navigation Tags. Nous attendons ensuite que l'URL de la nouvelle page contienne /tags et, aussi, que le contenu HTML de la nouvelle page comporte un élément h1 avec le mot Tags.

Et pour lancer ce nouveau test, exécutez simplement docker run --rm -v ./cypress:/app/cypress cypress-test.

Comme vous pouvez le voir, ça fonctionne.

Navigation

Monter un volume

Donc, en utilisant -v ./cypress:/app/cypress, nous montons le dossier cypress de notre host dans le dossier /app/cypress du container. En modifiant un test sur notre host, Docker répliquera le changement dans le container.

Récupérer les screenshots​

Ok, créons un troisième test et, cette fois, nous allons provoquer une erreur.

Créez un troisième fichier.

Attention

Si vous êtes attentif, vous remarquerez une faute d'orthographe, et c'est volontaire.

describe("Joomla Test", () => {
it("use tags and display Joomla posts", () => {
cy.visit("https://www.avonture.be");
// Find the "TAGS" link and click it. Adjust the selector if needed.
cy.contains("a", "Tags").click();
// Assert that the URL includes '/tags'.
// cspell:disable-next-line
cy.contains("a", "jomla").click();
});
});

Ce test Cypress visite un site Joomla, clique sur le lien Tags, puis clique sur un élément contenant le texte 'jomla' pour vérifier que la navigation fonctionne correctement.

Relançons Cypress : docker run --rm -v ./cypress:/app/cypress cypress-test.

Quand une erreur survient, Cypress prend un screenshot, comme on le voit sur l'image ci-dessous :

Prise d'un screenshot

Comme vous le voyez sur l'image, Cypress a pris un screenshot et l'a enregistré dans le dossier /app/cypress/screenshots/. Ce dossier est à l'intérieur du container et c'est inutile : nous voulons le récupérer sur notre disque.

Pour cela, nous devons mettre à jour notre image Docker afin de créer un nouvel utilisateur. Au final, nous pourrons partager notre host avec l'instance Cypress en cours d'exécution et déposer sur notre disque les screenshots créés par Cypress.

Remplacez votre Dockerfile existant par celui-ci :

# cspell:ignore johndoe
ARG USER_ID=1000
ARG GROUP_ID=1000
ARG USER_NAME="johndoe"
FROM cypress/included:15.19.0
# Where we'll put our files in the image
WORKDIR /app
# We'll create our specific user
ARG USER_ID
ARG GROUP_ID
ARG USER_NAME
# Our user will be member of the standard node group too
RUN groupadd -g ${GROUP_ID} "${USER_NAME}" && \
useradd -u ${USER_ID} -g "${USER_NAME}" -G node -m "${USER_NAME}"
# Change the ownership of our /app folder
RUN chown -R "${USER_NAME}":"${USER_NAME}" /app
USER "${USER_NAME}"
# Copy the package.json file to the Docker image
COPY --chown="${USER_NAME}":"${USER_NAME}" package*.json ./
# And run npm install i.e. install Cypress
RUN npm install
# Copy files into our image
COPY --chown="${USER_NAME}":"${USER_NAME}" cypress/ ./cypress/
COPY --chown="${USER_NAME}":"${USER_NAME}" cypress.config.js ./
# Check Cypress installation
RUN npx cypress verify
# And run Cypress and specify we'll use Chrome
CMD ["npx", "cypress", "run", "--browser", "chrome"]

Ce Dockerfile construit une image Docker pour exécuter des tests Cypress dans un navigateur Chrome. Il part d'une image Cypress préconfigurée, crée un utilisateur non-root avec des permissions appropriées, copie les fichiers du projet, installe les dépendances npm, vérifie que Cypress fonctionne correctement, puis configure l'image pour lancer les tests Cypress au démarrage.

Le script ci-dessus va créer un utilisateur appelé johndoe dans l'image (le nom n'a pas d'importance ici) mais, le plus important, c'est que cet utilisateur aura un UID / GID spécifique.

Ces paramètres sont des arguments de build et nous devons les initialiser comme ceci : clear ; docker build --build-arg USER_ID=$(id -u) --build-arg GROUP_ID=$(id -g) -t cypress-test .

Information

Les commandes id -u et id -g retournent l'ID de notre utilisateur (très probablement 1000) et son ID de groupe (ici aussi, très probablement 1000).

Cela dit à Docker d'utiliser notre propre user id et group id (ceux que nous utilisons sur notre host) lors de la construction de l'image. Donc, en bref, johndoe ce sera nous : si Docker crée un fichier sur notre disque, le fichier appartiendra à l'utilisateur ayant le même UID / GID, donc à nous.

Maintenant que c'est expliqué, nous pouvons lancer la commande complète comme ceci : clear ; docker build --build-arg USER_ID=$(id -u) --build-arg GROUP_ID=$(id -g) -t cypress-test . && docker run --rm -v ./cypress:/app/cypress cypress-test.

Nous montons toujours notre dossier cypress courant dans le container grâce au flag -v ./cypress:/app/cypress mais c'est bidirectionnel. Désormais, les fichiers créés par Cypress dans le container (dans le dossier /app/cypress) seront aussi copiés sur notre disque. Et comme nous avons pris le temps de créer un utilisateur spécifique dans l'image Docker, les fichiers créés par Docker nous appartiendront.

Notre workspace actuel ressemble à ceci dans VSCode :

vscode avec nos trois tests

En lançant docker run --rm -v ./cypress:/app/cypress cypress-test une nouvelle fois, nous voyons maintenant les changements :

Tag Joomla

Cypress a pris un screenshot et l'a enregistré sur notre disque. Maintenant, c'est très clair en regardant l'image : l'erreur concerne la vérification -contains a, jomla sur la page Tags. Oups, il y a une faute de frappe.

Éditez le fichier cypress/e2e/joomla.cy.js et corrigez la faute en écrivant cy.contains('a', 'joomla').click();. Relancez Cypress : l'erreur est résolue et le screenshot a disparu.

Conclusion​

L'idée de ce tutoriel est de rester simple, nous n'irons donc pas plus loin ici.

Si vous êtes francophone, rendez-vous sur Openclassrooms, il y a un très bon tutoriel sur Cypress.


🦋 Rejoignez la conversation sur BlueskyUn compte Bluesky gratuit est nécessaire pour aimer, repartager ou commenter. Ce bloc interroge l'API publique de Bluesky directement depuis votre navigateur (sans cookie, sans connexion) — votre adresse IP parvient donc aux serveurs de Bluesky dès que cette section se charge.

Chargement des commentaires…

Cet article vous a-t-il été utile ?
Avez-vous suivi les étapes de cet article ?