E2E Testing: En vejledning og arkitekturguide
End-to-end-test (E2E) hjælper med at validere de vigtigste flows i din applikation, f.eks. brugerloginforespørgsler. I forbindelse med front-end-udvikling hjælper E2E-tests med at verificere, om den korrekte brugergrænseflade er blevet præsenteret. For backend-udvikling hjælper E2E-tests med at verificere, om et vigtigt flow i dine backend-tjenester returnerer det forventede output.
Dette indlæg vil introducere dig til E2E-testning og give dig handlingsanvisende tips. Vi vil også forklare, hvordan du skriver genanvendelige tests, så de lettere kan bruges til at oprette E2E-tests. Som du måske ved, er E2E-tests ofte en stor frustration for udviklere, da de kræver en stor indsats at skrive, køre og vedligeholde.
Først skal vi se på, hvor E2E-tests er placeret i softwaretestpyramiden.
Placering af E2E-tests i testpyramiden
Når vi ser på testpyramiden, finder vi fire hovedtesttyper, der hjælper os med at sikre kodens kvalitet:
- E2E-tests hjælper med at verificere stier af høj værdi i din applikation. Med andre ord hjælper de med at verificere brugerhistorier, da de ofte repræsenterer flows i din applikation.
- Integrationstests hjælper med at verificere integrationen af flere funktioner eller komponenter. Integrationstests kan fortælle dig, om din kode fungerer sammenhængende med andre funktioner.
- Enhedstests hjælper med at verificere funktionernes forretningslogik. Unit-tests er den mest grundlæggende form for testning, og de sikrer, at forretningslogikken er korrekt.
- Sidst må vi ikke glemme statisk analyse eller statisk testning. Statisk testning hjælper med at finde stavefejl eller typefejl.
I henhold til denne pyramide bør de fleste tests være enhedstests, med færre integrationstests og endnu færre E2E-tests. Det er dog stadig vigtigt at verificere flows i din applikation. E2E-tests er svære at vedligeholde og kræver en stor indsats. Derfor bør du kun verificere de vigtigste flows med E2E-tests. Andre testtyper som f.eks. integrations- og enhedstest burde allerede give dig tilstrækkelig tillid til din kodebase.
Differente E2E-teststrategier
Lad mig fortælle dig, at der findes forskellige strategier. Vi kan vælge mellem horisontal E2E-testning og vertikal E2E-testning. Begge strategier er værd at udforske, da de giver dig mulighed for at teste forskellige scenarier. Lad os lære, hvad hver strategi gør.
Strategi #1: Vertikal End-to-End-testning
Denne strategi fokuserer på at teste alle lag af testpyramiden. Den omfatter enhedstest, integrationstest og UI-test. Dit mål er at teste en komponent på et granulært niveau ved hjælp af enhedstests, teste, hvordan en komponent opfører sig, når den interagerer med andre komponenter ved hjælp af integrationstests, og endelig at verificere komponentens opførsel, når brugerne interagerer via brugergrænsefladen.
Mest almindeligvis ønsker du at bruge en kontinuerlig integrationspipeline til at automatisere disse tests for hvert kodecommit eller pull request.
Strategi nr. 2: Horisontal End-to-End-testning
Horisontal E2E-testning fokuserer på at verificere et komplet brugerflow. Her er et eksempel på et flow for en webshop:
- Åbn produktside
- Vælg produktstørrelse
- Føj produkt til indkøbskurv
- Gå til kassen
- Fuldfør adresse- og betalingsoplysninger
- Fuldfør betaling
- Vis indkøbsbekræftelsesskærm
Her ønsker vi at verificere hver enkelt transaktion i brugerflowet. Ofte verificerer denne type test interaktionen mellem forskellige applikationer og verificerer tilstandsændringer for disse applikationer.
Bemærk, at disse typer test er dyre at skrive. Det kræver en del tid at definere brugerstrømme og skrive disse tests. Prøv derfor at fokusere på kritiske transaktionsveje for din applikation.
Sørg dog for at teste disse kritiske brugerstrømme for forskellige betingelser. Denne strategi giver dig mulighed for at få et fuldstændigt billede af brugerflowets robusthed. Disse betingelser omfatter:
- Komplekse timingsscenarier: F.eks. er en koncertbillet kun tilgængelig for dig i 15 minutter.
- Forskellige dataindtastninger eller manglende data.
- Flowbrud: En bruger beslutter sig for at forlade kassesiden for at se en anden produktside. Vi skal f.eks. verificere, om komponenten gemmer checkout-status.
Næste punkt: Lad os lære, hvornår du skal skrive E2E-tests.
Når du skal skrive E2E-tests
Du ved måske ikke, at E2E-tests er dyre tests at køre i din continuous integration pipeline. De kræver ofte en masse forberedelse, f.eks. oprettelse af en database, der efterligner produktionsdata. Desuden repræsenterer de nogle gange tidskrævende flows i din applikation. Derfor kan de være langsomme og kræve flere ressourcer for at blive udført.
Brug E2E-tests til at verificere de vigtigste flows i din applikation. Eksempler på flows af høj værdi omfatter:
- Login og logout
- Registrér en ny bruger
- Lægge en vare i indkøbskurven
- Ændre din adgangskode
- Alle andre vigtige flows i forbindelse med din tjeneste
Glem dog ikke at verificere den forretningslogik, du skriver, med enheds- og integrationstests. Kombinationen af både enheds- og integrationstests bør give dig masser af tillid til kvaliteten af din kode. E2E-tests hjælper dig med at øge denne tillid for kritiske stier.
Her er nogle handlingsorienterede tips til at skrive E2E-tests.
Tips til at skrive E2E-tests
Fokus på at skrive genanvendelige tests
Det første og vigtigste tip er at skrive små, uafhængige, genanvendelige tests og komponenter. Dette giver dig mulighed for at sætte flere små komponenter sammen for at skabe komplette end-to-end-brugerstrømme nemmere. I stedet for at skrive en masse brugerdefinerede komponenter, der kun skal bruges af E2E-tests, skal du fokusere på at skrive genanvendelige komponenter.
Skrivning af små, uafhængige komponenter hjælper med genbrug af kode og reducerer tiden til fejlfinding. Det er også lettere at opdatere små komponenter, når funktionaliteten eller brugerflowet ændres.
Tænk altid på årsagen til at skrive en E2E-test
Når du ønsker at dække et bestemt flow med en E2E-test, skal du overveje, om det er værd at dække. Test kun brugerstrømme af høj værdi med E2E-tests. Du bør f.eks. ikke teste, om der vises en fejlmeddelelse, når en bruger indtaster en forkert e-mail-adresse. Dette er en alt for simpel use case, som ikke passer til en E2E-test. Dette krav kan simpelthen testes med en enhedstest.
På den anden side er det værd at teste, om login-siden omdirigerer dig til den rigtige applikationsside, når du har logget ind med succes. Dette er et værdifuldt flow for, at dine brugere kan bruge applikationen. Kort sagt skal du altid overveje årsagen til at skrive en E2E-test.
E2E-tests bør ikke afhænge af implementeringsdetaljer
Du ønsker ikke at opdatere E2E-tests, hver gang du ændrer implementeringsdetaljer for et bestemt flow. Derfor ønsker du at skrive komponenter, der giver dig mulighed for at abstrahere implementeringsdetaljer. E2E-test bliver meget nemmere at vedligeholde og sjovere at skrive, når implementeringsdetaljerne er skjult i komponenter. Kort sagt bør E2E-tests være uafhængige af implementeringsdetaljer.
Næst skal vi se på faldgruberne ved E2E-tests.
Faldgruber ved E2E-testning
Her er en liste over almindelige faldgruber i forbindelse med E2E-testning:
- E2E-tests bør ikke forsøge at teste så meget som muligt på én gang. Ofte skriver udviklere enorme E2E-tests, der verificerer alle aspekter af brugerflowet. Hold tingene enkle og verificer de vigtigste aspekter af dit brugerflow. For et loginflow behøver du f.eks. kun at verificere, om brugeren blev omdirigeret til applikationssiden. Dette vil gøre det lettere for udviklere at vedligeholde og opdatere E2E-tests.
- Når en E2E-test fejler, kan det være svært at finde den nøjagtige årsag til fejlen. Du kan dog reducere den nødvendige fejlfindingsindsats ved at dække din forretningslogik med enheds- og integrationstests. Nogle værktøjer giver også en god rodårsagsanalyse, herunder skærmbilleder og konsollogs af fejlslagne testtrin, hvilket kan reducere tiden til fejlfinding.
- E2E-tests kræver en betydelig mængde tid i din continuous integration (CI)-pipeline (CI). De kan blokere din CI-pipeline, hvilket forsinker den samlede udvikling. Det betyder, at du måske skal investere i din CI-pipeline for at have et par pipelines mere til at køre tests.
- E2E-tests er en kontinuerlig indsats. Hver gang der tilføjes ny funktionalitet eller gammel funktionalitet ændres, er det sandsynligt, at du bliver nødt til at opdatere dine E2E-tests. Vi kan dog reducere denne indsats ved at skrive genanvendelige komponenter, der abstraherer implementeringsdetaljer. Desuden bruger nogle værktøjer AI til at hjælpe med at tilpasse testene, når koden ændres, hvilket reducerer testvedligeholdelsen.
Nu skal vi kort se på forskellene mellem systemtest og E2E-testning.
Systemtest vs. E2E-test – hvad er forskellen?
Så, hvad er forskellen mellem systemtest og E2E-test? Systemtestning fokuserer på at validere både de funktionelle som ikke-funktionelle krav. Ofte udføres den af et eksternt team, der behandler applikationen som en sort boks. Med andre ord ved de ikke noget om applikationens funktion bortset fra de krav, den skal opfylde.
Denne form for testning forveksles imidlertid ofte med E2E-testning, da systemtestning er en form for E2E-testning. Systemtestning verificerer dog meget mere end E2E-testning. Ved systemtestning måles f.eks. skalerbarhed, ydeevne eller pålidelighed. Hvorimod E2E-testning fokuserer på korrekt udfyldelse af brugerstrømme.
Sidst skal vi opsummere læringerne fra denne artikel.
Konklusion om E2E
End-to-end-tests er ret kraftfulde, da de hjælper med at validere højværdi brugerstrømme eller brugerhistorier. De er med til at garantere kvaliteten af din applikation.
Men det kan kræve en betydelig tid og indsats at skrive og vedligeholde E2E-tests. Det er muligt at reducere denne indsats ved at skrive små, genanvendelige komponenter, der abstraherer implementeringsdetaljer. Nogle værktøjer hjælper også med at skabe mere modstandsdygtige tests ved at bruge AI eller flere attributter til at identificere hvert element. Derfor behøver du ikke at opdatere E2E-tests, hver gang implementeringsdetaljerne ændres for brugerstrømme af høj værdi. Desuden giver genanvendelige komponenter dig mulighed for at kæde disse komponenter sammen for nemt at oprette E2E-teststrømme.
E2E-tests bør dække de vigtigste flows i din applikation. De tester de flows, som dine brugere og kunder følger for at få værdi fra din applikation. Hvis de ikke kan logge ind eller tilføje en vare til en indkøbskurv, vil de enten forlade applikationen (hvis de kan) eller ringe til support, hvis de er tvunget til at bruge din applikation. Du ønsker f.eks. at dække flowet for login og logout, men er mindre interesseret i at verificere en fejlmeddelelse efter indtastning af en forkert e-mail-adresse.
I sidste ende skal E2E-tests være sjove at skrive. De bør ikke kræve en masse tid og kræfter at skrive og vedligeholde. Hold E2E-tests enkle og fokuser på genanvendelige komponenter, og du vil se gode resultater!
Dette indlæg er skrevet af Michiel Mulders. Michiel er en passioneret blockchain-udvikler, der elsker at skrive teknisk indhold. Udover det elsker han at lære om marketing, UX-psykologi og iværksætteri. Når han ikke skriver, nyder han sikkert en belgisk øl!