Gå til hovedinnhold

Hvordan skrive akseptansekrav

Denne guiden viser hvordan du går fra et behov til velformulerte akseptansekrav som kan automatiseres.

Målgruppe

  • Produktledere
  • Domeneeksperter
  • Utviklere
  • Testere
  • Brukere som deltar i kravworkshops

Hvorfor akseptansekrav?

Akseptansekrav beskriver hva systemet skal gjøre fra brukerens perspektiv, ikke hvordan det skal implementeres. Gode akseptansekrav:

  • Er lesbare for alle - både tekniske og ikke-tekniske interessenter
  • Fungerer som dokumentasjon - alltid oppdatert fordi testene kjører mot dem
  • Driver testene - samme krav blir til automatiserte tester
  • Reduserer misforståelser - alle snakker samme språk
Levende dokumentasjon

Tradisjonell dokumentasjon blir fort utdatert. Når kravene våre driver testene, vet vi at dokumentasjonen stemmer - fordi testene feiler hvis den ikke gjør det.

Steg 1: Eksempelkartlegging-workshop

Eksempelkartlegging er en strukturert workshop-teknikk for å utforske krav før implementasjon. Den tar typisk 25-30 minutter per brukerhistorie.

Deltakere

  • Produktleder - kjenner forretningsbehovet
  • Domeneekspert - kjenner reglene og prosessene
  • Utvikler - forstår tekniske muligheter og begrensninger
  • Tester - tenker på edge cases og hva som kan gå galt
  • Bruker (når mulig) - representerer sluttbrukeren

Utstyr

Du trenger fire farger med Post-it-lapper eller kort:

FargeInnholdBeskrivelse
🟨 GulBrukerhistorieFunksjonaliteten som diskuteres
🟦 BlåRegelForretningsregler og akseptansekriterier
🟩 GrønnEksempelKonkrete eksempler som illustrerer regelen
🟥 RødSpørsmålUbesvarte spørsmål og uklarheter

Hvordan kjøre workshopen

1. Start med brukerhistorie (gul lapp)

Skriv brukerhistorien på en gul lapp og plasser den øverst.

Som saksbehandler
ønsker jeg å opprette et lokalt opptak
slik at studenter kan søke på utdanningstilbud

2. Identifiser regler (blå lapper)

Still spørsmålet: "Hvilke regler gjelder for denne funksjonaliteten?"

Eksempler på regler:

  • "Et opptak må ha en søknadsfrist"
  • "Opptaket må være publisert for å være søkbart"
  • "Kun autoriserte brukere kan opprette opptak"

Plasser hver regel som en blå lapp under den gule.

3. Finn eksempler for hver regel (grønne lapper)

For hver blå regel, still spørsmålet: "Kan du gi meg et konkret eksempel?"

Regel: Et opptak må ha en søknadsfrist

Eksempler:
- Søknadsfrist 15.04.2025 → Opptak opprettes OK
- Ingen søknadsfrist → Feilmelding "Søknadsfrist er påkrevd"
- Søknadsfrist i fortiden → Feilmelding "Søknadsfrist må være i fremtiden"

4. Fang opp spørsmål (røde lapper)

Når noe er uklart, skriv det på en rød lapp i stedet for å gjette.

- Kan søknadsfristen endres etter publisering?
- Hva skjer med eksisterende søknader hvis fristen endres?
- Hvem skal varsles når et opptak opprettes?

Når er workshopen ferdig?

Workshopen er ferdig når:

  • Alle regler har minst ett eksempel
  • Røde spørsmål er dokumentert (ikke nødvendigvis besvart)
  • Teamet føler de forstår omfanget
For mange kort?

Hvis du ender opp med mange blå eller røde kort, er brukerhistorien sannsynligvis for stor. Vurder å dele den opp.

Eksempel på ferdig eksempelkart

🟨 Opprette lokalt opptak

🟦 Opptak må ha påkrevde felt
🟩 Navn, type, søknadsfrist → OK
🟩 Mangler navn → "Navn er påkrevd"
🟩 Mangler søknadsfrist → "Søknadsfrist er påkrevd"

🟦 Søknadsfrist må være gyldig
🟩 Frist 15.04.2025 → OK
🟩 Frist i fortiden → "Må være i fremtiden"

🟦 Kun autoriserte brukere kan opprette
🟩 Saksbehandler → Kan opprette
🟩 Student → Får ikke tilgang

🟥 Kan frist endres etter publisering?
🟥 Skal det sendes varsel ved opprettelse?

Steg 2: Skrive Gherkin-krav

Etter workshopen konverterer vi eksempelkartet til Gherkin-format. De grønne eksemplene blir til scenarioer.

Vi skriver Gherkin på norsk. Se Cucumber Gherkin Reference for full syntaks og norske nøkkelord.

Eksempel: Fra eksempelkart til Gherkin

La oss konvertere eksempelkartet fra workshopen:

# language: no
@opptak
Egenskap: Opprette lokalt opptak
Som saksbehandler
ønsker jeg å opprette et lokalt opptak
slik at studenter kan søke på utdanningstilbud

Bakgrunn:
Gitt at jeg er logget inn som saksbehandler
Og at jeg er på opptakssiden

Regel: Opptak må ha påkrevde felt

Scenario: Vellykket opprettelse med alle påkrevde felt
Når jeg oppretter et nytt lokalt opptak
Og jeg setter navn til "Høstopptak 2025"
Og jeg setter type til "Lokalt opptak"
Og jeg setter søknadsfrist til "15.04.2025"
Og jeg lagrer opptaket
skal opptaket "Høstopptak 2025" vises i listen

Scenario: Feilmelding ved manglende navn
Når jeg oppretter et nytt lokalt opptak
Og jeg lar navn være tomt
Og jeg prøver å lagre opptaket
skal jeg se feilmeldingen "Navn er påkrevd"

Regel: Søknadsfrist må være gyldig

Scenariomal: Validering av søknadsfrist
Når jeg setter søknadsfrist til "<frist>"
skal jeg se "<resultat>"

Eksempler:
| frist | resultat |
| 15.04.2025 | Frist lagret |
| 01.01.2020 | Søknadsfrist må være i fremtiden |

Regel: Kun autoriserte brukere kan opprette opptak

Scenariomal: Tilgangskontroll for opprettelse
Gitt at jeg er logget inn som <rolle>
Når jeg prøver å opprette et nytt opptak
skal jeg <resultat>

Eksempler:
| rolle | resultat |
| saksbehandler | kunne opprette opptaket |
| student | se "Ingen tilgang" |

Legg merke til hvordan:

  • Regler fra eksempelkartet (blå kort) blir Regel:-seksjoner
  • Eksempler (grønne kort) blir Scenario:
  • Varianter av samme regel samles i Scenariomal: med Eksempler:-tabell
Tenk på gjenbrukbarhet

Når du skriver steg, vurder om de kan gjenbrukes i andre scenarioer. Generiske formuleringer gjør det lettere å automatisere senere. Spør gjerne Claude om hvilke steg som finnes fra før.

# Gjenbrukbart - kan brukes i mange scenarioer
Når jeg lagrer

# Mindre gjenbrukbart - spesifikt for opptak
Når jeg lagrer opptaket

Steg 3: Bruke Claude Code for å generere Gherkin

Vi har en Claude Code-skill som kan hjelpe deg å konvertere resultater fra eksempelkartlegging til Gherkin-filer. Du får den automatisk når du åpner repoet med Claude.

Slik bruker du skillen

  1. Start Claude Code i terminalen
  2. Kjør kommandoen /skrive-krav
  3. Beskriv funksjonaliteten eller lim inn resultatene fra en eksempelkartlegging
  4. Svar på spørsmål - Claude vil stille oppfølgingsspørsmål for å sikre korrekt forståelse
  5. Gå gjennom den genererte feature-filen

Eksempel på dialog

> /skrive-krav

Claude: Hva skal funksjonaliteten gjøre?

> Vi hadde en eksempelkartlegging-workshop om å opprette lokalt opptak.
> Reglene vi fant var:
> 1. Opptak må ha påkrevde felt (navn, type, søknadsfrist)
> 2. Søknadsfrist må være i fremtiden
> 3. Kun saksbehandlere kan opprette

Claude: Hvem er aktørene?

> Saksbehandler

Claude: Jeg fant noen eksisterende steps som kan gjenbrukes:
- `at jeg er logget inn som {rolle}` - bruker-kontekst.steps.ts
- `jeg lagrer` - felles.steps.ts

Noen spørsmål før jeg genererer kravfilen:
1. Hvilken feilmelding vises ved manglende navn?
2. Hvilken feilmelding vises ved ugyldig søknadsfrist?
...
Ikke gjett - spør!

Skillen er designet for å stille spørsmål i stedet for å gjette. Hvis du ikke vet svaret, si det - da dokumenteres det som et åpent spørsmål i feature-filen.

Mappestruktur

Alle krav lagres i krav/-mappen i fs-repoet, organisert i tre nivåer:

NivåBeskrivelseEksempel
DomeneOverordnet forretningsområde02 Opptak
SubdomeneLogisk gruppering innenfor domenet11 Opptak, 12 Registrere søknad
KapabilitetSpesifikk funksjonalitet01 Opptak, 01 Søknad
fs/
└── krav/
├── 01 Forberede studier/ # Domene
│ └── 10 Administrere utdanning/ # Subdomene
│ ├── 01 Utdanning/ # Kapabilitet
│ │ └── utdanning.feature
│ └── 02 Utdanningstilbud/ # Kapabilitet
│ └── utdanningstilbud.feature

├── 02 Opptak/ # Domene
│ ├── 10 Regelverk/ # Subdomene
│ │ ├── 02 Krav/ # Kapabilitet
│ │ │ └── opptakskrav.feature
│ │ └── 04 Kvoter/ # Kapabilitet
│ │ └── kvoter.feature
│ ├── 11 Opptak/ # Subdomene
│ │ └── 01 Opptak/ # Kapabilitet
│ │ └── opptak.feature
│ └── 12 Registrere søknad/ # Subdomene
│ └── 01 Søknad/ # Kapabilitet
│ └── soknad.feature

├── 03 Gjennomføre studier/
├── 04 Kompetanse/
├── 05 Opplysninger om person/
└── ...
  • Mapper: Bruk nummer for sortering, etterfulgt av beskrivende navn
    • Domener starter typisk på 01, 02, 03...
    • Subdomener starter typisk på 10, 11, 12...
    • Kapabiliteter starter typisk på 01, 02, 03...
  • Feature-filer: Bruk snake_case med beskrivende navn
    • opptak.feature
    • soknad.feature
    • utdanningstilbud.feature

Beste praksis

1. Bruk Bakgrunn for felles kontekst

Bakgrunn: definerer forutsetningene som gjelder for alle scenarioer i en feature. Her beskriver du hvem brukeren er, hvor de befinner seg, og hvilke data som må finnes fra før.

Bakgrunn:
Gitt at jeg er logget inn som saksbehandler
Og at det finnes et opptak som heter "UHG 2026"
Og at jeg er på hovedsiden i fs-admin

Bakgrunnen kjøres før hvert scenario, så alle scenarioer starter fra samme utgangspunkt. Dette gjør scenarioene kortere og lettere å lese, fordi du slipper å gjenta de samme forutsetningene i hvert scenario.

2. Ett scenario, én atferd

Hvert scenario skal teste én ting. Hvis du vil teste flere ting, lag flere scenarioer.

# Bra - ett scenario per atferd
Scenario: Gyldig søknadsfrist aksepteres
...

Scenario: Ugyldig søknadsfrist avvises
...

# Dårlig - flere atferder i ett scenario
Scenario: Validering av søknadsfrist
Når jeg setter gyldig frist
skal den aksepteres
Når jeg setter ugyldig frist
skal den avvises

3. Bruk Scenariomal for varianter

Når du har flere scenarioer med samme struktur men ulike verdier, bruk Scenariomal:

# Bra - én mal med eksempler
Scenariomal: Validering av søknadsfrist
Når jeg setter søknadsfrist til "<frist>"
skal jeg se "<resultat>"

Eksempler:
| frist | resultat |
| 15.04.2025 | Frist akseptert |
| 01.01.2020 | Søknadsfrist må være i fremtiden |

# Dårlig - dupliserte scenarioer
Scenario: Gyldig frist
Når jeg setter søknadsfrist til "15.04.2025"
skal jeg se "Frist akseptert"

Scenario: Ugyldig frist
Når jeg setter søknadsfrist til "01.01.2020"
skal jeg se "Søknadsfrist må være i fremtiden"

4. Bruk konkrete eksempler

Unngå generiske verdier. Bruk realistiske data som forteller en historie:

# Bra - konkret og forståelig
Gitt at studenten "Emma Hansen" er registrert på "Bachelor i informatikk"
Når Emma søker om permisjon for "Høst 2025"

# Dårlig - generisk og uklart
Gitt at en student er registrert
Når studenten søker om permisjon

5. Deklarativt over imperativt

Fokuser på hva som skal skje, ikke hvordan:

# Bra - deklarativt (hva)
Når jeg oppretter et nytt opptak med navn "Høstopptak 2025"

# Dårlig - imperativt (hvordan)
Når jeg klikker på "Nytt opptak"-knappen
Og jeg skriver "Høstopptak 2025" i navnefeltet
Og jeg klikker på "Lagre"-knappen

6. Bruk Regel for forretningsregler

Regel: dokumenterer en forretningsregel som systemet må følge. Scenarioene under regelen er eksempler som illustrerer hvordan regelen fungerer i praksis:

Regel: Søknadsfrist må være i fremtiden
Scenario: Gyldig frist aksepteres
...
Scenario: Frist i fortiden avvises
...

Regel: Kun saksbehandlere kan opprette opptak
Scenario: Saksbehandler kan opprette
...
Scenario: Student får ikke tilgang
...

7. Dokumenter åpne spørsmål

Hvis noe er uavklart, dokumenter det i stedet for å gjette:

# ÅPNE SPØRSMÅL:
# - Kan søknadsfristen endres etter publisering?
# - Hvem skal varsles ved opprettelse?

@wip
Egenskap: Opprette lokalt opptak
...

Tags

Bruk tags for å kategorisere og filtrere krav. Tags deles inn i fem kategorier:

Prioritet (MoSCoW)

Angir hvor viktig kravet er for produktet.

TagBeskrivelse
@mustMå ha - kritisk funksjonalitet
@shouldBør ha - viktig, men ikke kritisk
@couldKan ha - ønskelig hvis tid
@wontIkke nå - utenfor scope for nå

Status

Angir implementasjonsstatus for kravet.

TagBeskrivelse
@implementedFunksjonaliteten er ferdig utviklet
@in-progressUnder utvikling
@plannedPlanlagt, men ikke påbegynt

Testtype

Angir hvordan kravet skal verifiseres.

TagBeskrivelse
@e2eEnde-til-ende-test gjennom nettleser
@integrationIntegrasjonstest mot API
@demoDemonstrasjonsscenario

Automatisk kjøring

Angir om og når testen skal kjøres automatisk.

TagMiljøBeskrivelse
@smokeTestKjøres hver gang FSAdmin får et nytt image
@nightlyFunctionaltestKjøres hver natt

Jira-kobling

Tags på formatet @XXX-NNN (tekst-bindestrek-tall) kan brukes til å koble krav til Jira-saker. Dette gir oversikt over hvilke krav som hører til samme oppgave, og er nyttig i planlegging.

@STUD-1234 @must
Egenskap: Opprette lokalt opptak
...

@STUD-1234 @should
Egenskap: Redigere lokalt opptak
...

I eksempelet over er begge kravene koblet til Jira-saken STUD-1234, slik at teamet kan se hvilke krav som skal løses sammen.

Hva er forskjellen?

  • @smoke er raske, kritiske tester som verifiserer at grunnleggende funksjonalitet fungerer etter en ny utrulling. Disse kjøres mot testmiljøet.
  • @nightly er mer omfattende tester som kjøres mot functionaltest-miljøet hver natt. Her kan du inkludere tester som tar lengre tid eller tester mer komplekse brukerreiser.

Når bør du bruke @smoke?

  • Testen verifiserer kritisk funksjonalitet som må fungere
  • Testen er rask å kjøre
  • Testen er stabil og gir ikke falske negativer
Smoke-tester må rydde opp etter seg

Siden @smoke-tester kjøres mot testmiljøet ved hver utrulling, må de alltid rydde opp data de oppretter. Hvis en test oppretter et opptak, må den slette opptaket når testen er ferdig. Dette sikrer at testmiljøet ikke fylles opp med testdata og at testene kan kjøres gjentatte ganger uten å feile.

@smoke
Scenario: Opprette og slette opptak
Når jeg oppretter et nytt opptak med navn "Smoke-test opptak"
skal opptaket være synlig i listen
# Rydd opp
Når jeg sletter opptaket "Smoke-test opptak"
skal opptaket ikke lenger være synlig

Når bør du bruke @nightly?

  • Testen er ferdig implementert og stabil
  • Funksjonaliteten bør overvåkes kontinuerlig
  • Scenarioet har automatiserte stegdefinisjoner
  • Testen kan ta litt lengre tid å kjøre

Når bør du ikke bruke disse taggene?

  • Testen er under utvikling (@in-progress)
  • Scenarioet beskriver ønsket funksjonalitet som ikke er implementert ennå
  • Testen er ustabil eller avhenger av eksterne systemer som ofte er nede
Ikke legg til tags for tidlig

Et scenario uten @smoke eller @nightly er fortsatt verdifullt som dokumentasjon. Vent med å legge til disse taggene til testen er stabil og funksjonaliteten er ferdig utviklet.

Kombinere tags

Et scenario kan ha flere tags fra ulike kategorier:

@must @implemented @e2e @smoke
Scenario: Bruker kan logge inn med Feide
...

Sjekkliste

Før du anser et krav som ferdig:

  • Har kravet kommet fra en workshop eller dialog med interessenter?
  • Er alle regler representert med scenarioer?
  • Er hvert scenario uavhengig og tester én ting?
  • Er eksemplene konkrete og realistiske?
  • Er åpne spørsmål dokumentert?
  • Er filen plassert i riktig mappe?
  • Er tags lagt til (@e2e, @integration, etc.)?

Neste steg

Når kravene er skrevet, har teamet en felles forståelse av hva som skal utvikles.

Etter at utviklingen er ferdig, er det naturlig å automatisere kravene som tester:

  • Integrasjonstester for å verifisere forretningslogikk og API-kontrakter
  • Ende-til-ende-tester for kritiske brukerreiser

Se Hvordan skrive automatiserte akseptansetester for hvordan du implementerer testene.

Verktøy for å redigere feature-filer

Det finnes flere måter å jobbe med feature-filene i fs-repoet, avhengig av dine behov og tekniske forutsetninger.

Claude Code (lokalt)

For utviklere og teknisk personell som har Claude Code installert.

Fordeler:

  • Full tilgang til hele repoet
  • Kan kjøre /skrive-krav-skillen for assistert Gherkin-generering
  • Direkte redigering, commit og push

Slik bruker du det:

  1. Klon fs-repoet lokalt
  2. Åpne terminalen i repo-mappen
  3. Kjør claude for å starte Claude Code
  4. Be Claude om å opprette eller redigere feature-filer

GitHub Web

For sporadisk bruk uten installasjon.

Fordeler:

  • Ingen installasjon nødvendig
  • Fungerer i nettleseren
  • Kan bruke Claude.ai som assistent i en annen fane

Slik bruker du det:

  1. Gå til fs-repoet på GitHub
  2. Naviger til feature-filen du vil redigere
  3. Klikk på blyant-ikonet (Edit)
  4. Gjør endringene (bruk Claude.ai i en annen fane for hjelp)
  5. Scroll ned og velg "Create a new branch" og commit endringen
  6. Lag en pull request så teamet kan gå gjennom endringene
Kun for nye krav

Hvis du endrer på .feature-filer som allerede har taggen @smoke eller @nightly, er det sannsynlig at du knekker automatiske tester. GitHub Web anbefales derfor bare når du jobber med nye krav som ikke har disse taggene.

Hvilken metode bør jeg velge?

RolleAnbefalt metode
AlleClaude Code lokalt
Eksterne brukereGitHub Web

Ressurser