Hvordan skrive automatiserte akseptansetester
Når ny funksjonalitet er utviklet basert på akseptansekravene, må det vurderes hvilke av kravene som skal ha automatiserte tester.
Målgruppe
- Utviklere som skal implementere step definitions
Forutsetninger
- Du har lest Hvordan skrive akseptansekrav
- Du har satt opp utviklingsmiljøet (se README i fs-repoet)
Hvordan playwright-bdd fungerer
Vi bruker playwright-bdd for å koble Gherkin-krav til Playwright-tester. Verktøyet fungerer som en bro mellom de lesbare kravene og den faktiske testkoden.
Fra Gherkin til kjørbar test
Flyten fra krav til kjørbar test består av flere steg:
- bddgen leser
.feature-filer frakrav/-mappen - Genererer Playwright-testfiler i
.features-gen/ - Hvert steg i Gherkin matches mot en step definition
- Playwright kjører de genererte testene
Du trenger aldri å redigere filene i .features-gen/ - de genereres automatisk hver gang du kjører bddgen. Det du skriver er step definitions som kobler Gherkin-stegene til faktisk testkode.
Step definitions
En step definition er en funksjon som utfører det et Gherkin-steg beskriver. Når Gherkin-filen sier Når jeg lagrer, må det finnes en step definition som vet hvordan "lagre" skal utføres i applikasjonen.
When('jeg lagrer', async ({ page }) => {
await page.getByRole('button', { name: 'Lagre' }).click();
});
Step definitions skrives i TypeScript og bruker Playwright for å interagere med applikasjonen. De plasseres i steps/-mappen, organisert etter domene.
Parametre i steps
For å unngå å skrive mange nesten-like step definitions, kan du bruke parametre. playwright-bdd støtter flere parametertyper som {string} for tekst i anførselstegn, {int} for heltall, og {word} for enkeltord. Se playwright-bdd dokumentasjonen for komplett oversikt.
Gjenbrukbarhet
En av de største fordelene med BDD er at step definitions kan gjenbrukes på tvers av scenarioer. Når du skriver Når jeg lagrer i ti forskjellige scenarioer, trenger du bare én step definition.
Finn eksisterende steps
Før du skriver en ny step definition, sjekk alltid om det finnes en som kan gjenbrukes. Søk i tester/steps/-mappen etter relevante nøkkelord. Over tid bygger teamet opp et bibliotek av gjenbrukbare steps som gjør det raskere å automatisere nye krav.
Hvis du gir Claude Code tilgang til fs-repoet, kan den raskt finne eksisterende steps som matcher det du trenger. Spør for eksempel "finnes det en step for å logge inn?" eller "hvilke steps har vi for opptak?".
Skriv gjenbrukbare steps
Tenk på gjenbrukbarhet når du formulerer steg. En step som Når jeg lagrer kan brukes i mange kontekster, mens Når jeg lagrer opptaket kun fungerer i opptak-scenarioer. Generiske formuleringer gir mer fleksibilitet, men noen ganger er det riktig å være spesifikk for å gjøre scenarioet mer lesbart.
Implementere nye steps
Når du må skrive en ny step definition, trenger du å forstå hvordan applikasjonen fungerer. Du må vite hvilke UI-elementer som finnes og hvordan brukeren interagerer med dem.
Hvis du gir Claude Code tilgang til frontend-repoene (fs-admin, min-kompetanse) og GraphQL-skjemaet, kan den hjelpe deg med å finne riktige selektorer for UI-elementer eller forstå hvilke felter og mutasjoner som er tilgjengelige i API-et.
Bruk Playwright Codegen med Claude
Playwright Codegen lar deg ta opp interaksjoner i nettleseren og generere kode. Kombinert med Claude får du en effektiv arbeidsflyt for å lage step definitions.
For FS-Admin (saksbehandler):
npx playwright codegen --lang no-Nb $FS_ADMIN_URL
For MinKompetanse (student/søker):
npx playwright codegen --lang no-Nb $MIN_KOMPETANSE_URL
Flagget --lang no-Nb sikrer at Codegen bruker norsk locale, slik at knapper og elementer får riktige navn.
Arbeidsflyt:
- Kjør Codegen-kommandoen i terminalen
- Logg inn med Feide testbruker
- Gjennomfør hele scenarioet du skal automatisere
- Kopier all generert kode
- Lim koden inn i Claude sammen med scenarioet fra feature-filen
- Claude strukturerer koden til gjenbrukbare step definitions
Eksempel på dialog med Claude:
> Jeg har kjørt gjennom dette scenarioet i Codegen:
>
> Scenario: Opprette nytt opptak
> Gitt at jeg er logget inn som saksbehandler
> Når jeg oppretter et nytt opptak med navn "Test"
> Så skal opptaket vises i listen
>
> Her er koden Codegen genererte:
> [lim inn kode]
>
> Kan du lage step definitions for dette?
Claude: Jeg ser at du har disse interaksjonene. La meg først sjekke
hvilke steps som allerede finnes...
[Claude finner eksisterende steps og lager kun de som mangler]
Claude vil identifisere hvilke steps som allerede finnes, og lage nye step definitions kun for de som mangler.
userContext-fixture
Vi bruker alltid userContext-fixture i stedet for page. Dette gir oss konsistent håndtering av roller og innlogging på tvers av alle tester.
Viktig: Alle scenarioer må starte med innlogging:
Gitt at jeg er logget inn som administrator
Dette er påkrevd fordi userContext bruker lazy initialization - den oppretter ikke en nettleserkontekst før switchTo() kalles. Tilgjengelige roller er:
| Rolle | Applikasjon | Beskrivelse |
|---|---|---|
administrator | FS-Admin | Saksbehandler |
person | MinKompetanse | Student/søker |
personsok-administrator | FS-Admin | Saksbehandler med tilgang til personopplysninger |
I step definitions bruker du userContext.currentPage for å få tilgang til Playwright sin page:
When('jeg navigerer til opptak', async ({ userContext }) => {
await userContext.currentPage.getByRole('link', { name: 'Opptak' }).click()
})
Organiser steps etter domene
Step definitions organiseres i filer etter domene. Generelle steps som "lagre", "navigere" og "logge inn" legges i common.steps.ts, mens domenespesifikke steps legges i egne filer som opptak.steps.ts eller student.steps.ts. Dette gjør det enklere å finne eksisterende steps og forstå hva som er tilgjengelig.
Testdata og isolasjon
Hver test skal opprette og bruke kun sin egen testdata. Dette sikrer at tester kan kjøres uavhengig av hverandre og i vilkårlig rekkefølge.
Setup og teardown
Når Gherkin-filen har en Bakgrunn: som sier "det finnes et opptak som heter X", må step definition opprette dette opptaket før scenarioet kjører. Etter at scenarioet er ferdig, skal testdataen ryddes opp.
Dette betyr at:
- Tester er ikke avhengige av data som "tilfeldigvis" finnes i testmiljøet
- Tester påvirker ikke hverandre
- Tester kan kjøres parallelt
- Feilsøking blir enklere fordi hver test starter fra kjent tilstand
Navngivning av testdata
Bruk unike, gjenkjennelige navn på testdata slik at det er lett å identifisere hvilken test som opprettet dem. Dette gjør det enklere å feilsøke hvis noe går galt.
Repoer og tilganger
For å skrive gode step definitions trenger du forståelse for applikasjonene du tester. Dette innebærer tilgang til relevante repoer:
| Repo | Innhold | Brukes til |
|---|---|---|
| fs | Krav og tester | Feature-filer og step definitions |
| fs-admin | Admin-frontend | Forstå UI-elementer |
| min-kompetanse | Student-frontend | Forstå UI-elementer |
Kjøre testene lokalt
Fra tester/-mappen i fs-repoet har du flere kommandoer tilgjengelig:
| Kommando | Beskrivelse |
|---|---|
npm test | Kjører bddgen og alle tester |
npm run test:headed | Kjører tester med synlig nettleser (nyttig for debugging) |
npm run test:smoke | Kjører kun tester tagget med @smoke |
npm run test:nightly | Kjører kun tester tagget med @nightly |
npm run test:nightly:headed | Kjører nightly-tester med synlig nettleser |
npm run bddgen | Genererer testfiler fra features uten å kjøre testene |
Når kjører testene automatisk?
Testene kjøres automatisk i to situasjoner:
- Smoke-tester (
@smoke) kjøres hver gang en merge til fs-admin lager et nytt image. Dette verifiserer at kritisk funksjonalitet fungerer etter deploy. - Nightly-tester (
@nightly) kjøres hver natt mot functionaltest-miljøet. Dette fanger opp regresjoner på tvers av alle repoer.
Automatiske kjøringer gir oss et sikkerhetsnett, men erstatter ikke lokal testing under utvikling.