Tests e2e prêts pour CI pour Angular avec Cypress et TypeScript en moins de 60 minutes

Cet article a pour but de décrire comment vous pouvez mettre en place des tests de bout en bout pour Angular avec Cypress incluant TypeScript. Vous écrirez vos tout premiers tests e2e et les rendrez prêts à être exécutés sur un CircleCI en tant que système d’intégration continue à chaque mise à jour de votre référentiel.

Le test de bout en bout (en abrégé e2e) est un type de test logiciel qui valide le système logiciel ainsi que son intégration avec des interfaces externes. Le but du test de bout en bout est d’exercer un scénario complet de type production.

Source : https://www.guru99.com/end-to-end-testing.html.

Aperçu

  • Qu’est-ce que Cypress ?
  • Prérequis
  • Mise en place de Cypress
  • Écrire quelques tests
  • Mise en place de l’intégration continue
  • Conclusion et références

J’ai une expérience de développement front-end dans le .NET & WPF et je me souviens des moments où nous avons évalué des frameworks coûteux pour écrire des tests de bout en bout pour nos projets. Après de nombreuses évaluations et des semaines, voire des mois de code glue personnalisé et de développement d’infrastructures de test par-dessus les outils existants, nous avons finalement réussi à faire fonctionner quelques tests e2e. Ils étaient fragiles, échouaient souvent à cause d’ajustements manuels que nous devions faire ou de problèmes avec des runners floconneux dans le pipeline d’intégration continue.

Quelques années plus tard, avec Angular et Protractor par défaut pour les tests e2e, nous étions toujours basés sur les objets de page, Selenium Web Driver et les tests continuaient à être plutôt peu fiables. Aucun framework commercial coûteux et aucune infrastructure personnalisée n’étaient nécessaires. Mais était-ce amusant d’écrire des tests e2e ? Non.

Mais nous sommes en 2020 maintenant et le temps est venu pour de nouveaux héros de se lever. 🚀

C’est quoi Cypress ?

Cypress promet des tests rapides, faciles et fiables pour tout ce qui s’exécute dans un navigateur. Il n’est pas basé sur Selenium Web Driver qui utilise des connexions réseau pour interagir avec votre navigateur. Au lieu de cela, Cypress est un exécuteur de test qui s’exécute à l’intérieur de votre navigateur à côté de votre application web et a donc un contrôle direct sur celle-ci.

Sans entrer dans tous les détails, cela ne rend pas seulement Cypress plus rapide et plus fiable, cela ouvre également la porte à beaucoup d’autres fonctionnalités intéressantes comme

  • le débogage du voyage dans le temps,
  • la capture et l’enregistrement faciles,
  • les attentes automatiques.

En plus de toutes ces fonctionnalités, Cypress a une expérience de développeur (DX) qui est presque inégalée. Avez-vous déjà vu un message dans les journaux d’erreurs de votre build raté qui vous dit exactement ce que vous avez mal fait, vous indique les bonnes dépendances à ajouter et vous renvoie également vers un site de documentation explicatif décrivant le problème ? C’est à cela que ressemble Cypress. Il est construit par des développeurs pour des développeurs.

L'erreur de Cypress sur le serveur de build vous indiquant comment la corriger

Ci-après, nous allons installer Cypress pour un projet Angular frais créé avec le CLI. Nous écrirons quelques tests e2e et conclurons par l’exécution de ceux-ci par un système de build automatisé. Toutes ces étapes ne devraient pas prendre plus de 60 minutes. Nous essayons de garder les étapes aussi courtes que possible, en tirant parti des outils existants comme les schémas Angular, les bibliothèques et les modèles communs.

Prérequis

Ce guide suppose que vous avez un projet d’application Angular 9 standard. Si ce n’est pas le cas, vous pouvez en créer un comme vous le feriez normalement avec le CLI Angular. Si vous n’avez pas le CLI installé globalement, vous pouvez faire usage de la commande npx qui l’installera temporairement à la volée:

npx @angular/cli new <app-name>

Mise en place de Cypress

Pour mettre en place Cypress avec TypeScript aussi rapidement que possible, nous faisons usage d’un schéma existant développé par BrieBug.

À la racine de votre projet Angular, vous pouvez ouvrir le terminal et entrer la commande suivante :

ng add @briebug/cypress-schematic --addCypressTestScripts

Si le CLI n’est pas installé globalement, la commande ng peut ne pas être disponible directement. Vous pouvez imposer l’utilisation de la ng locale depuis la package.json:

npm run ng -- add @briebug/cypress-schematic # In case 'ng' could not be found

Nous pouvons supprimer Protractor en toute sécurité car il sera complètement remplacé. Au cours de l’installation, certains binaires ont été téléchargés parce que Cypress est livré avec une interface utilisateur groupée Electron comme un exécuteur de test interactif.

Utilisant le drapeau --addCypressTestScripts, deux scripts npm pratiques ont été ajoutés pour rendre le travail avec Cypress plus confortable. L’un pour exécuter les tests e2e headless et l’autre script exécutant les tests avec le runner Cypress UI:

 // package.json scripts "cy:run": "cypress run", "cy:open": "cypress open"

Si vous deviez exécuter un de ces scripts de manière autonome, le test échouerait parce qu’il tente de router vers http://localhost:4200 où rien n’est servi pour le moment. Afin de corriger cela, nous devons ouvrir un deuxième terminal et servir notre application Angular au préalable avec npm start.

Heureusement, le schéma a ajusté la commande e2e afin que cela soit fait pour vous automatiquement par le constructeur CLI. Vous pouvez servir l’application et démarrer le test e2e en utilisant la commande suivante:

npm run e2e

Cypress détectera que nous l’avons lancé pour la première fois. Il vérifie son installation et ajoute quelques fichiers d’exemple initiaux. Après l’ouverture de l’interface utilisateur, nous pouvons voir un test qui a déjà été créé pour nous.

L'interface utilisateur de Cypress après cy:open

Sélectionner le test va l’exécuter. Initialement, le test échouera parce que nous n’avons pas réellement testé quelque chose correctement. Nous allons corriger cela maintenant.

Échec du test qui n'est pas encore implémenté

Écrire quelques tests

Toute première étape, comme le proposent les meilleures pratiques de Cypress, nous définissons notre baseUrl global, afin de ne pas avoir à le dupliquer à chaque exécution de test. Ajoutez ce qui suit à la configuration cypress.json:

// cypress.json{ "baseUrl": "http://localhost:4200"}

Après cela, nous écrivons notre tout premier test smoke qui vérifie uniquement si le titre de l’application par défaut est défini sur la page de démarrage Angular. Par conséquent, changez le contenu du spec.ts en contenu suivant:

// spec.tsit('smoke test', () => { cy.visit('/'); cy.contains('cypress-e2e-testing-angular app is running!');});

Le test commence par router vers notre baseUrl et procède en interrogeant tout élément qui contient le texte cypress-e2e-testing-angular app is running !.

Tester les flux d’utilisateurs

Ce test devrait déjà fonctionner, mais écrivons-en des plus interactifs. Comme les e2e sont intrinsèquement plus lents que les tests unitaires, il est tout à fait correct d’avoir des tests e2e qui modélisent l’ensemble du flux utilisateur pour une fonctionnalité.

Par exemple, nous voulons vérifier si certaines caractéristiques de la page de départ sont valides : Notre page devrait contenir le titre et le texte ng generate dans le terminal par défaut, mais lorsque les utilisateurs cliquent sur le bouton Angular Material, nous voulons nous assurer que la commande ng add appropriée s’affiche dans la vue du terminal ci-dessous.

Vous pouvez remplacer le contenu de votre fichier de test par ceci:

// spec.tsdescribe('When Angular starting page is loaded', () => { beforeEach(() => { cy.visit('/'); }); it('has app title, shows proper command by default and reacts on command changes', () => { cy.contains('cypress-e2e-testing-angular'); cy.contains('.terminal', 'ng generate component xyz'); cy.contains('Angular Material').click(); cy.contains('.terminal', 'ng add @angular/material'); });});

Nous avons refacturé notre suite de tests en ajoutant un bloc describe pour capturer tous les tests qui s’exécutent lorsque la page de départ est chargée. Comme nous visitons le baseUrl à chaque fois, nous l’avons déplacé dans l’appel beforeEach. Enfin, nous avons combiné les tests de fumée de base avec le test de la vue terminale sur la page de départ.

Il est important de savoir que vous ne devez pas stocker les résultats des requêtes de Cypress dans des variables, mais plutôt travailler avec des fermetures. De plus, nous avons sélectionné des éléments par classes CSS et contenu textuel, ce qui peut être trop fragile. Il est recommandé d’utiliser les attributs data- pour sélectionner les éléments.

Cypress a beaucoup de grandes fonctionnalités et de possibilités. Nous ne les couvrirons pas toutes car notre objectif est de nous concentrer sur le tout premier point de départ. La documentation officielle est vraiment bonne et couvre tout sur la façon d’interagir avec les éléments.

Si vous relancez cette suite de tests, vous devriez voir l’interface utilisateur cliquer à travers chaque scénario et les trois tests devraient passer cette fois. ✔✔✔

Exécution réussie de notre première suite de tests Cypress

Mise en place de l’intégration continue

Maintenant que nos tests s’exécutent localement, donnons le coup d’envoi d’un petit pipeline CI (intégration continue). Une bonne façon de se préparer à cela, est de créer des scripts npm et de les combiner afin que le système de construction puisse utiliser un seul script comme point d’entrée. En suivant cette méthode, vous pouvez essayer les étapes de l’intégration continue localement avant de les mettre en ligne. De plus, les scripts npm sont plutôt indépendants de tout système de construction réel.

Sur CI, nous devons démarrer notre serveur en arrière-plan et attendre qu’il regroupe notre application, ce qui peut prendre un certain temps. Ensuite, nous devons lancer l’exécuteur de tests Cypress, passer les tests et arrêter le serveur lorsque les tests sont terminés. Heureusement, nous pouvons faire tout cela avec un seul utilitaire appelé start-server-and-test comme décrit dans les docs de Cypress:

npm install --save-dev start-server-and-test

Après que cela soit installé, nous utilisons le service Angular qui est actuellement derrière npm start et le combinons avec la commande headless cy:run :

 // package.json scripts "start": "ng serve", "cy:run": "cypress run", "e2e:ci": "start-server-and-test start http://localhost:4200 cy:run"

Vous pourriez sûrement utiliser un build de production ou un build au préalable et servir l’app en utilisant n’importe quel serveur http. Par souci de concision, je vous laisse ces améliorations.

Circle CI

Pour notre exemple, nous avons choisi CircleCI car il s’intègre très bien à GitHub, y est couramment utilisé et dispose d’un plan gratuit. Vous pouvez utiliser tout autre système de CI comme Jenkins ou GitLab (avec lequel j’ai le plus d’expérience). Après avoir signé dans CircleCI et s’être connecté à notre compte GitHub, vous pouvez sélectionner le dépôt et créer un nouveau projet via leur tableau de bord.

Afin de configurer le pipeline, vous pourriez écrire un config.ymlen sélectionnant un modèle et en l’ajustant à vos besoins et éventuellement en exécutant le script e2e. Heureusement, Cypress dispose de configurations prêtes à l’emploi (appelées Orbs) pour CircleCI qui incluent déjà l’installation des dépendances, la mise en cache et ainsi de suite. Avant de pouvoir l’utiliser, nous devons nous rendre dans les paramètres de l’organisation pour activer les runners tiers.

# circleci/config.ymlversion: 2.1orbs: # This Orb includes the following: # - checkout current repository # - npm install with caching # - start the server # - wait for the server to respond # - run Cypress tests # - store videos and screenshots as artifacts on CircleCI cypress: cypress-io/cypress@1workflows: build: jobs: - cypress/run: start: npm start wait-on: 'http://localhost:4200' store_artifacts: true

Le pipeline n’a qu’une seule tâche : Exécuter tous les tests e2e. Il vérifie la branche actuelle, installe toutes les dépendances, y compris la mise en cache, démarre le serveur d’application et exécute nos tests. En outre, les vidéos (enregistrées par défaut) et les captures d’écran (au cas où les tests échouent) sont téléchargées en tant qu’artefacts CircleCI pour une inspection plus approfondie.*

CircleCI Dashboard

Conclusion

Les étapes de ce guide sont plutôt minimales. Vous pouvez utiliser votre projet Angular existant, modifier la configuration de vos suites de tests Cypress et écrire un grand nombre de tests plus significatifs. De plus, vous pouvez définir des scripts npm pour différents scénarios et environnements et, bien sûr, votre pipeline de construction tout entier peut être étendu avec le linting, les tests unitaires, la construction et même le déploiement de votre application. Néanmoins, ceci devrait être une première étape qui montre comment des tests automatisés de bout en bout peuvent être rapidement mis en place de nos jours.

Attendez jusqu’à ce que vous écriviez de vrais tests Cypress pour votre application. Vous allez vous amuser !

Mind blown gif

J’espère que vous trouverez également de la valeur dans cet article. Si vous avez des questions ou des remarques, faites-le moi savoir. Vos commentaires sont les bienvenus !

Vous pouvez trouver les sources de ce guide sur GitHub :

MrCube42 / cypress-e2e-testing-angular

Exemple d’application Angular 9 utilisant Cypress pour les tests de bout en bout.

CypressE2eTestingAngular

Ce projet a été généré avec Angular CLI version 9.0.6.

Serveur de développement

Exécutez ng serve pour un serveur de développement. Naviguez jusqu’à http://localhost:4200/. L’application se rechargera automatiquement si vous modifiez l’un des fichiers source.

Échafaudage de code

Exécutez ng generate component component-name pour générer un nouveau composant. Vous pouvez également utiliser ng generate directive|pipe|service|class|guard|interface|enum|module.

Build

Run ng build pour construire le projet. Les artefacts de construction seront stockés dans le répertoire dist/. Utilisez le drapeau --prod pour une construction de production.

Exécution des tests unitaires

Run ng test pour exécuter les tests unitaires via Karma.

Exécution des tests de bout en bout

Run npm run e2e pour exécuter les tests de bout en bout via Cypress.

Aide supplémentaire

Pour obtenir plus d’aide sur le CLI Angular, utilisez ng help ou allez consulter le README du CLI Angular.

.

Leave a Reply