CI-klare e2e-tests til Angular med Cypress og TypeScript på under 60 minutter

Denne artikel har til formål at beskrive, hvordan du kan opsætte end-to-end-tests til Angular med Cypress, herunder TypeScript. Du vil skrive dine allerførste e2e-tests og gøre dem klar til at køre på en CircleCI som et kontinuerligt integrationssystem med hver opdatering til dit repository.

End-to-end (kort e2e) test er en type softwaretest, der validerer softwaresystemet sammen med dets integration med eksterne grænseflader. Formålet med end-to-end-test er at udøve et komplet produktionslignende scenarie.

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

Oversigt

  • Hvad er Cypress?
  • Forudsætninger
  • Installation af Cypress
  • Skrivning af nogle tests
  • Installation af Continuous Integration
  • Konklusion og referencer

Jeg har en frontend-udviklingsbaggrund i Microsofts .NET & WPF og husker de tider, hvor vi evaluerede dyre frameworks for at skrive end-to-end tests til vores projekter. Efter en masse evalueringer og uger, ja, endda måneder med brugerdefineret glue-kode og udvikling af testinfrastrukturer oven på eksisterende værktøjer fik vi endelig nogle e2e-tests til at køre. De var skrøbelige, fejlede ofte på grund af manuelle justeringer, som vi måtte foretage, eller problemer med flaky runners i den kontinuerlige integrations-pipeline.

Som et par år senere med Angular og Protractor som standard for e2e-tests, var vi stadig baseret på sideobjekter, Selenium Web Driver og testene var fortsat ret upålidelige. Der var ikke brug for dyre kommercielle frameworks og brugerdefineret infrastruktur. Men var det sjovt at skrive e2e-tests? Nej.

Men vi er nu i 2020, og tiden er kommet til at nye helte skal opstå. 🚀

Hvad er Cypress?

Cypress lover hurtig, nem og pålidelig testning af alt, der kører i en browser. Det er ikke baseret på Selenium Web Driver, som bruger netværksforbindelser til at interagere med din browser. I stedet er Cypress en testkører, der kører inde i din browser ved siden af din webapplikation og derfor har har har direkte kontrol over den.

Suden at gå ind i alle detaljerne, gør dette ikke kun Cypress hurtigere og mere pålidelig, det åbner også op for en masse andre interessante funktioner som

  • tidsrejse debugging,
  • nem snapshotting og optagelse,
  • automatiske waitings.

Oven i alle funktionerne har Cypress en udvikleroplevelse (DX), der næsten er uovertruffen. Har du nogensinde set en meddelelse i fejllogfilerne for dit fejlslagne build, der fortæller dig præcis, hvad du gjorde forkert, peger dig på de rigtige afhængigheder, du skal tilføje, og som også linker til et forklarende dokumentationssted, der beskriver problemet? Det er sådan, Cypress føles. Det er bygget af udviklere til udviklere.

Cypress-fejl på build-serveren, der fortæller dig, hvordan du retter den

Nedenfor vil vi installere Cypress til et frisk Angular-projekt oprettet med CLI’en. Vi vil skrive nogle e2e-tests og afslutte med at køre disse af et automatiseret build-system. Alle disse trin bør ikke tage mere end 60 minutter. Vi forsøger at holde trinene så korte som muligt, idet vi udnytter eksisterende værktøjer som Angular Schematics, biblioteker og fælles skabeloner.

Forudsætninger

Denne vejledning forudsætter, at du har et standard Angular 9-app-projekt. Hvis ikke, kan du oprette et, som du normalt ville gøre med Angular CLI’en. Hvis du ikke har CLI’en installeret globalt, kan du gøre brug af kommandoen npx, der installerer den midlertidigt on the fly:

npx @angular/cli new <app-name>

Opsætning af Cypress

For at opsætte Cypress sammen med TypeScript så hurtigt som muligt, gør vi brug af et eksisterende skema udviklet af BrieBug.

I roden af dit Angular-projekt kan du åbne terminalen og indtaste følgende kommando:

ng add @briebug/cypress-schematic --addCypressTestScripts

Hvis CLI’en ikke er installeret globalt, er ng-kommandoen muligvis ikke tilgængelig direkte. Du kan gennemtvinge brugen af den lokale ng fra package.json:

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

Vi kan trygt fjerne Protractor, fordi den vil blive fuldstændig erstattet. Under installationen blev der hentet nogle binære filer, fordi Cypress kommer med et Electron-bundtet UI som en interaktiv test runner.

Ved hjælp af flaget --addCypressTestScripts blev der tilføjet to praktiske npm-scripts for at gøre arbejdet med Cypress mere behageligt. Et til at køre e2e-tests headless og det andet script, der kører testene med Cypress UI runner:

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

Hvis du skulle køre et af disse scripts standalone, ville testen fejle, fordi den forsøger at route til http://localhost:4200, hvor der ikke serveres noget i øjeblikket. For at løse dette er vi nødt til at åbne en anden terminal og servere vores Angular-applikation på forhånd med npm start.

Gluksomt nok justerede skemaet e2e-kommandoen, så dette gøres automatisk for dig af CLI-byggeren. Du kan servere applikationen og starte e2e-testen ved at bruge følgende kommando:

npm run e2e

Cypress vil registrere, at vi har lanceret den for første gang. Den verificerer sin installation og tilføjer nogle indledende eksempelfiler. Efter at brugergrænsefladen er blevet åbnet, kan vi se en test, der allerede er blevet oprettet for os.

Cypress UI efter cy:open

Vælg testen, så køres den. I første omgang vil testen mislykkes, fordi vi faktisk ikke har testet noget korrekt. Det retter vi nu.

Failing test, der ikke er implementeret endnu

Skrive nogle tests

Som et allerførste skridt, som foreslået i Cypress best practices, indstiller vi vores globale baseUrl, så vi ikke behøver at duplikere dette ved hver testudførelse. Tilføj følgende til konfigurationen cypress.json:

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

Dernæst skriver vi vores allerførste røgtest, som kun kontrollerer, om standard-apptitlen er indstillet på Angular-startssiden. Derfor ændrer vi indholdet af spec.ts til følgende indhold:

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

Testen starter med at route til vores baseUrl og fortsætter med at forespørge ethvert element, der indeholder teksten cypress-e2e-testing-angular app is running!.

Test af brugerstrømme

Denne test burde allerede fungere, men lad os skrive nogle mere interaktive test. Da e2e i sagens natur er langsommere end enhedstests, er det helt fint at have e2e-tests, der modellerer hele brugerflowet for en funktion.

For eksempel ønsker vi at kontrollere, om nogle egenskaber for startsiden er gyldige: Vores side skal som standard indeholde titlen og ng generate-teksten i terminalen, men når brugerne klikker på Angular Material-knappen, vil vi sikre, at den korrekte ng add-kommando vises i terminalvisningen nedenunder.

Du kan erstatte indholdet af din testfil med dette:

// 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'); });});

Vi refaktoriserede vores testsuite ved at tilføje en describe-blok for at fange alle tests, der kører, når startsiden indlæses. Da vi besøger baseUrl hver gang, flyttede vi dette ind i beforeEach-opkaldet. Endelig kombinerede vi de grundlæggende røgtests med testen for terminalvisningen på startsiden.

Det er vigtigt at vide, at du ikke skal gemme Cypress’ forespørgselsresultater i variabler, men i stedet arbejde med closures. Desuden har vi udvalgt elementer efter CSS-klasser og tekstindhold, hvilket kan være for skørt. Det anbefales at bruge data--attributter til udvælgelse af elementer.

Cypress har mange gode funktioner og muligheder. Vi vil ikke dække dem alle, fordi vores mål er at fokusere på det allerførste startpunkt. Den officielle dokumentation er rigtig god og dækker alt om, hvordan man interagerer med elementer.

Hvis du genudfører denne testsuite, bør du se brugergrænsefladen klikke sig igennem hvert scenarie, og alle tre tests bør bestå denne gang. ✔✔✔

Kørsel af vores første Cypress-testsuite med succes

Opsætning af Continuous Integration

Nu, hvor vores tests kører lokalt, skal vi sparke en lille CI-pipeline (continuous integration) i gang. En god måde at forberede dette på, er at oprette npm-scripts og kombinere dem, så build-systemet kan bruge et enkelt script som entry point. Ved at følge denne metode kan du prøve CI-trinnene lokalt, før du skubber dem online. Desuden er npm-scripts ret uafhængige af et egentligt build-system.

På CI skal vi starte vores server i baggrunden og vente på, at den bundler vores applikation, hvilket kan tage et stykke tid. Derefter skal vi starte Cypress test runneren, gå igennem testene og lukke serveren ned, når testene er færdige. Heldigvis kan vi gøre alt dette med et enkelt hjælpeprogram kaldet start-server-and-test som beskrevet i Cypress-dokumentationen:

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

Når dette er installeret, bruger vi Angular serve, som i øjeblikket ligger bag npm start, og kombinerer det med headless cy:run-kommandoen:

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

Du kan helt sikkert bruge et produktionsbyg eller bygge i forvejen og servere appen ved hjælp af en hvilken som helst http-server. Af hensyn til overskueligheden vil jeg lade disse forbedringer være op til dig.

Circle CI

I vores eksempel vælger vi CircleCI, fordi det integrerer meget godt med GitHub, er almindeligt anvendt der og har en gratis plan. Du kan bruge et hvilket som helst andet CI-system som Jenkins eller GitLab (som jeg har mest erfaring med). Når du har logget ind på CircleCI og oprettet forbindelse til vores GitHub-konto, kan du vælge repository og oprette et nyt projekt via deres dashboard.

For at konfigurere pipelinen kan du skrive en config.yml ved at vælge en skabelon og justere den efter dine behov og til sidst køre e2e-scriptet. Heldigvis har Cypress en klar til brug konfigurationer (kaldet Orbs) til CircleCI, som allerede omfatter installation af afhængigheder, caching osv. Før vi kan bruge den, skal vi besøge organisationsindstillingerne for at aktivere tredjepartsløbere.

# 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

Pipelinen har kun ét job: Kør alle e2e-tests. Den tjekker den aktuelle gren, installerer alle afhængigheder, herunder caching, starter applikationsserveren og kører vores tests. Derudover uploades videoer (optaget som standard) og skærmbilleder (hvis testene fejler) som CircleCI-artefakter til yderligere inspektion. *

CircleCI Dashboard

Konklusion

Trinene i denne vejledning er ret minimale. Du kan bruge dit eksisterende Angular-projekt, du kan ændre konfigurationen af dine Cypress-testsuiter og skrive en masse mere meningsfulde tests. Desuden kan du definere npm-scripts til forskellige scenarier og miljøer, og selvfølgelig kan hele din build-pipeline udvides med linting, unit testing, opbygning og endda deployering af din applikation. Ikke desto mindre bør dette være et første skridt, som viser, hvor hurtigt automatiserede end-to-end-tests kan opstilles i dag.

Venter til du skriver rigtige Cypress-tests til din applikation. Du vil få det sjovt!

Mind blown gif

Jeg håber, at du også vil finde noget værdi i denne artikel. Hvis du har nogle spørgsmål eller bemærkninger, så lad mig endelig vide det. Din feedback er meget velkommen!

Du kan finde kilderne til denne vejledning på GitHub:

MrCube42 / cypress-e2e-testing-angular

Eksempel på Angular 9-app, der bruger Cypress til end-to-end-test.

CypressE2eTestingAngular

Dette projekt blev genereret med Angular CLI version 9.0.6.

Udviklingsserver

Kør ng serve for en dev-server. Naviger til http://localhost:4200/. Appen genindlæses automatisk, hvis du ændrer nogen af kildefilerne.

Kode stillads

Kør ng generate component component-name for at generere en ny komponent. Du kan også bruge ng generate directive|pipe|service|class|guard|interface|enum|module.

Build

Run ng build for at bygge projektet. Byggeartefakterne gemmes i mappen dist/. Brug --prod-flaget for et produktionsbyg.

Kør enhedstest

Kør ng test for at udføre enhedstestene via Karma.

Kør end-to-end-test

Kør npm run e2e for at udføre end-to-end-testene via Cypress.

Videre hjælp

For at få mere hjælp til Angular CLI skal du bruge ng help eller gå ind og tjek Angular CLI README.

Leave a Reply