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
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:
| Farge | Innhold | Beskrivelse |
|---|---|---|
| 🟨 Gul | Brukerhistorie | Funksjonaliteten som diskuteres |
| 🟦 Blå | Regel | Forretningsregler og akseptansekriterier |
| 🟩 Grønn | Eksempel | Konkrete eksempler som illustrerer regelen |
| 🟥 Rød | Spørsmål | Ubesvarte 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
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
Så 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
Så 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>"
Så 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
Så 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:medEksempler:-tabell
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
- Start Claude Code i terminalen
- Kjør kommandoen
/skrive-krav - Beskriv funksjonaliteten eller lim inn resultatene fra en eksempelkartlegging
- Svar på spørsmål - Claude vil stille oppfølgingsspørsmål for å sikre korrekt forståelse
- 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?
...
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å | Beskrivelse | Eksempel |
|---|---|---|
| Domene | Overordnet forretningsområde | 02 Opptak |
| Subdomene | Logisk gruppering innenfor domenet | 11 Opptak, 12 Registrere søknad |
| Kapabilitet | Spesifikk funksjonalitet | 01 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/
└── ...
Navngivning
- 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...
- Domener starter typisk på
- Feature-filer: Bruk
snake_casemed beskrivende navnopptak.featuresoknad.featureutdanningstilbud.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
Så skal den aksepteres
Når jeg setter ugyldig frist
Så 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>"
Så 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"
Så skal jeg se "Frist akseptert"
Scenario: Ugyldig frist
Når jeg setter søknadsfrist til "01.01.2020"
Så 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.
| Tag | Beskrivelse |
|---|---|
@must | Må ha - kritisk funksjonalitet |
@should | Bør ha - viktig, men ikke kritisk |
@could | Kan ha - ønskelig hvis tid |
@wont | Ikke nå - utenfor scope for nå |
Status
Angir implementasjonsstatus for kravet.
| Tag | Beskrivelse |
|---|---|
@implemented | Funksjonaliteten er ferdig utviklet |
@in-progress | Under utvikling |
@planned | Planlagt, men ikke påbegynt |
Testtype
Angir hvordan kravet skal verifiseres.
| Tag | Beskrivelse |
|---|---|
@e2e | Ende-til-ende-test gjennom nettleser |
@integration | Integrasjonstest mot API |
@demo | Demonstrasjonsscenario |
Automatisk kjøring
Angir om og når testen skal kjøres automatisk.
| Tag | Miljø | Beskrivelse |
|---|---|---|
@smoke | Test | Kjøres hver gang FSAdmin får et nytt image |
@nightly | Functionaltest | Kjø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?
@smokeer raske, kritiske tester som verifiserer at grunnleggende funksjonalitet fungerer etter en ny utrulling. Disse kjøres mot testmiljøet.@nightlyer 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
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"
Så skal opptaket være synlig i listen
# Rydd opp
Når jeg sletter opptaket "Smoke-test opptak"
Så 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
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.
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:
- Klon fs-repoet lokalt
- Åpne terminalen i repo-mappen
- Kjør
claudefor å starte Claude Code - 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:
- Gå til fs-repoet på GitHub
- Naviger til feature-filen du vil redigere
- Klikk på blyant-ikonet (Edit)
- Gjør endringene (bruk Claude.ai i en annen fane for hjelp)
- Scroll ned og velg "Create a new branch" og commit endringen
- Lag en pull request så teamet kan gå gjennom endringene
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?
| Rolle | Anbefalt metode |
|---|---|
| Alle | Claude Code lokalt |
| Eksterne brukere | GitHub Web |