CI-klara e2e-tester för Angular med Cypress och TypeScript på mindre än 60 minuter

Denna artikel syftar till att beskriva hur du kan konfigurera end-to-end-tester för Angular med Cypress och TypeScript. Du kommer att skriva dina allra första e2e-tester och göra dem redo att köras på en CircleCI som ett kontinuerligt integrationssystem med varje uppdatering av ditt arkiv.

End-to-end (kort e2e) testning är en typ av mjukvarutestning som validerar mjukvarusystemet tillsammans med dess integration med externa gränssnitt. Syftet med end-to-end-test är att utöva ett fullständigt produktionsliknande scenario.

Källa: https://www.guru99.com/end-to-end-testing.html.

Översikt

  • Vad är Cypress?
  • Förutsättningar
  • Installation av Cypress
  • Skrivning av tester
  • Installation av kontinuerlig integration
  • Slutsats och referenser

Jag har en bakgrund som utvecklare av frontend i Microsofts .NET & WPF och minns de tider då vi utvärderade kostsamma ramverk för att skriva end-to-end-tester för våra projekt. Efter många utvärderingar och veckor, till och med månader av anpassad limkod och utveckling av testinfrastrukturer ovanpå befintliga verktyg fick vi äntligen igång några e2e-tester. De var sköra, misslyckades ofta på grund av manuella justeringar som vi var tvungna att göra eller problem med flaky runners i den kontinuerliga integrationspipelinen.

Några år senare med Angular och Protractor som standard för e2e-tester, var vi fortfarande baserade på page objects, Selenium Web Driver och testerna fortsatte att vara ganska opålitliga. Inga dyra kommersiella ramverk och anpassad infrastruktur behövdes. Men var det roligt att skriva e2e-tester? Nej.

Hursomhelst är vi år 2020 nu och tiden har kommit för nya hjältar att uppstå. 🚀

Vad är Cypress?

Cypress lovar snabb, enkel och tillförlitlig testning av allt som körs i en webbläsare. Den är inte baserad på Selenium Web Driver som använder nätverksanslutningar för att interagera med din webbläsare. Istället är Cypress en testkörare som körs inne i din webbläsare bredvid din webbapplikation och har därför har har direkt kontroll över den.

Och utan att gå in på alla detaljer gör detta inte bara Cypress snabbare och mer tillförlitlig, det öppnar också dörren för många andra intressanta funktioner som

  • tidsresedebuggning,
  • enkel snapshotting och inspelning,
  • automatiska väntetider.

Ovanpå alla dessa funktioner har Cypress en utvecklarupplevelse (DX) som är nästan oöverträffad. Har du någonsin sett ett meddelande i felloggarna för din misslyckade byggning som talar om exakt vad du gjorde fel, pekar ut rätt beroenden att lägga till och även länkar till en förklarande dokumentationssida som beskriver problemet? Detta är vad Cypress känns som. Den är byggd av utvecklare för utvecklare.

Cypress fel på byggservern som talar om hur du ska åtgärda det

Härnäst kommer vi att installera Cypress för ett färskt Angular-projekt som skapats med CLI. Vi skriver några e2e-tester och avslutar med att köra dessa av ett automatiserat byggsystem. Alla dessa steg bör inte ta mer än 60 minuter. Vi försöker hålla stegen så korta som möjligt och utnyttjar befintliga verktyg som Angular Schematics, bibliotek och gemensamma mallar.

Förutsättningar

Denna guide förutsätter att du har ett standard Angular 9 app-projekt. Om så inte är fallet kan du skapa ett på samma sätt som du normalt skulle göra med Angular CLI. Om du inte har CLI installerat globalt kan du använda kommandot npx som installerar det tillfälligt i farten:

npx @angular/cli new <app-name>

Uppsättning av Cypress

För att sätta upp Cypress tillsammans med TypeScript så snabbt som möjligt använder vi oss av ett befintligt schema utvecklat av BrieBug.

I roten av ditt Angular-projekt kan du öppna terminalen och ange följande kommando:

ng add @briebug/cypress-schematic --addCypressTestScripts

Om CLI inte har installerats globalt kanske ng-kommandot inte är tillgängligt direkt. Du kan tvinga fram användningen av det lokala ng från package.json:

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

Vi kan säkert ta bort Protractor eftersom det kommer att ersättas fullständigt. Under installationen hämtades några binärer eftersom Cypress levereras med ett Electron-bundled UI som en interaktiv testkörare.

Med hjälp av flaggan --addCypressTestScripts lades två praktiska npm-skript till för att göra arbetet med Cypress bekvämare. Ett för att köra e2e-tester headless och det andra skriptet som kör testerna med Cypress UI runner:

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

Om du skulle köra ett av dessa skript fristående skulle testet misslyckas eftersom det försöker röra sig till http://localhost:4200 där inget serveras för tillfället. För att åtgärda detta måste vi öppna en andra terminal och servera vår Angular-applikation i förväg med npm start.

Turligtvis justerade schemat e2e-kommandot så att detta görs automatiskt åt dig av CLI-byggaren. Du kan servera applikationen och starta e2e-testet med följande kommando:

npm run e2e

Cypress kommer att upptäcka att vi startade den för första gången. Den verifierar sin installation och lägger till några inledande exempelfiler. Efter att användargränssnittet har öppnats kan vi se ett test som redan har skapats för oss.

Cypress användargränssnitt efter cy:open

Väljs testet kommer det att köras. Initialt kommer testet att misslyckas eftersom vi faktiskt inte testade något ordentligt. Vi kommer att åtgärda detta nu.

Felande test som inte är implementerat ännu

Skriva några tester

Som ett mycket första steg, enligt förslaget i Cypress bästa praxis, ställer vi in vår globala baseUrl, så att vi inte behöver dubblera detta vid varje testkörning. Lägg till följande i konfigurationen cypress.json:

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

Därefter skriver vi vårt allra första röktest som bara kontrollerar om standardtiteln för appen är inställd på Angular-startsidan. Ändra därför innehållet i spec.ts till följande innehåll:

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

Testet börjar med att dirigera till vår baseUrl och fortsätter med att fråga alla element som innehåller texten cypress-e2e-testing-angular app is running!.

Testning av användarflöden

Det här testet bör redan fungera, men vi skriver några mer interaktiva sådana. Eftersom e2e-tester i sig är långsammare än enhetstester är det helt okej att ha e2e-tester som modellerar hela användarflödet för en funktion.

Till exempel vill vi kontrollera om vissa egenskaper hos startsidan är giltiga: Vår sida ska innehålla titeln och ng generate-texten i terminalen som standard, men när användaren klickar på Angular Material-knappen vill vi försäkra oss om att rätt ng add-kommando visas i terminalvyn nedan.

Du kan ersätta innehållet i din testfil med detta:

// 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 har omarbetat vår testföljd genom att lägga till ett describe-block som fångar upp alla tester som körs när startsidan laddas. Eftersom vi besöker baseUrl varje gång flyttade vi detta till beforeEach-anropet. Slutligen kombinerade vi de grundläggande röktesterna med testet för terminalvyn på startsidan.

Det är viktigt att veta att du inte ska lagra Cypress’ frågeresultat i variabler, utan istället arbeta med closures. Dessutom valde vi element genom CSS-klasser och textinnehåll, vilket kan vara för skört. Det rekommenderas att använda data--attribut för att välja element.

Cypress har många bra funktioner och möjligheter. Vi kommer inte att täcka alla eftersom vårt mål är att fokusera på den allra första startpunkten. Den officiella dokumentationen är riktigt bra och täcker allt om hur man interagerar med element.

Om du kör den här testsviten på nytt bör du se hur användargränssnittet klickar sig igenom varje scenario och alla tre testerna bör klara den här gången. ✔✔✔

Kör vår första Cypress-testsekvens framgångsrikt

Uppsättning av Continuous Integration

Nu när våra tester körs lokalt, låt oss sparka igång en liten CI-pipeline (continuous integration). Ett bra sätt att förbereda sig för detta är att skapa npm-skript och kombinera dem så att byggsystemet kan använda ett enda skript som ingångspunkt. Genom att följa den här metoden kan du prova CI-stegen lokalt innan du skickar dem online. Dessutom är npm-skript ganska oberoende av något egentligt byggsystem.

På CI måste vi starta vår server i bakgrunden och vänta på att den ska paketera vår applikation, vilket kan ta ett tag. Sedan måste vi starta Cypress test runner, gå igenom testerna och stänga av servern när testerna är klara. Som tur är kan vi göra allt detta med ett enda verktyg som heter start-server-and-test enligt beskrivningen i Cypress-dokumentationen:

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

När detta är installerat använder vi Angular serve som för närvarande ligger bakom npm start och kombinerar det med kommandot 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"

Du kan säkert använda ett produktionsbygge eller bygga i förväg och servera appen med någon http-server. För korthetens skull lämnar jag dessa förbättringar upp till dig.

Circle CI

För vårt exempel väljer vi CircleCI eftersom det integrerar mycket väl med GitHub, är vanligt förekommande där och har en gratis plan. Du kan använda något annat CI-system som Jenkins eller GitLab (som jag har mest erfarenhet av). Efter att ha loggat in på CircleCI och anslutit till vårt GitHub-konto kan du välja repository och skapa ett nytt projekt via deras instrumentpanel.

För att konfigurera pipelinen kan du skriva ett config.yml genom att välja en mall och justera den efter dina behov och så småningom köra e2e-skriptet. Lyckligtvis har Cypress färdiga konfigurationer (kallade Orbs) för CircleCI som redan inkluderar installation av beroenden, caching och så vidare. Innan vi kan använda den måste vi besöka organisationsinställningarna för att aktivera tredjepartsrunners.

# 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

Pipeline har bara ett jobb: Kör alla e2e-tester. Den kontrollerar den aktuella grenen, installerar alla beroenden inklusive caching, startar applikationsservern och kör våra tester. Dessutom laddas videor (inspelade som standard) och skärmdumpar (om testerna misslyckas) upp som CircleCI-artefakter för ytterligare inspektion. *

CircleCI Dashboard

Slutsats

Steggen i den här guiden är ganska minimala. Du kan använda ditt befintliga Angular-projekt, du kan ändra konfigurationen av dina Cypress-testsviter och skriva många mer meningsfulla tester. Dessutom kan du definiera npm-skript för olika scenarier och miljöer och naturligtvis kan hela din byggpipeline utökas med linting, enhetstestning, byggande och till och med distribution av din applikation. Detta bör dock vara ett första steg som visar hur snabbt automatiserade end-to-end-tester kan sättas upp i dag.

Vänta tills du skriver riktiga Cypress-tester för din applikation. Du kommer att ha roligt!

Mind blown gif

Jag hoppas att du också hittar något värde i denna artikel. Om du har några frågor eller anmärkningar är det bara att låta mig veta. Din feedback är mycket välkommen!

Du hittar källorna till den här guiden på GitHub:

MrCube42 / cypress-e2e-testing-angular

Exempel på Angular 9-app som använder Cypress för end-to-end-testning.

CypressE2eTestingAngular

Detta projekt genererades med Angular CLI version 9.0.6.

Utvecklingsserver

Kör ng serve för en utvecklingsserver. Navigera till http://localhost:4200/. Appen laddas automatiskt om om du ändrar någon av källfilerna.

Code scaffolding

Kör ng generate component component-name för att generera en ny komponent. Du kan också använda ng generate directive|pipe|service|class|guard|interface|enum|module.

Build

Run ng build för att bygga projektet. Byggartefakterna kommer att lagras i katalogen dist/. Använd flaggan --prod för ett produktionsbygge.

Kör enhetstester

Kör ng test för att utföra enhetstesterna via Karma.

Kör end-to-end-tester

Kör npm run e2e för att utföra end-to-end-testerna via Cypress.

Hjälp

För att få mer hjälp med Angular CLI använd ng help eller kolla in Angular CLI README.

Leave a Reply