# ”Kör om, det brukar gå”: flakiga tester är en skuld, inte otur

- Författare: [Jonas Odencrants](https://paperphyte.com/konsulter/jonas-odencrants), [Paperphyte](https://paperphyte.com)
- Publicerad: 2026-10-16
- Kategori: Delivery Engineering
- Etiketter: Delivery Engineering, Flakiga tester, Testning, CI/CD, Karantän, DeLaval
- Källa: <https://paperphyte.com/anteckningsbok/flakiga-tester>

Bygget blev rött på ett test ingen rört på ett halvår, så någon klickade ”kör om” och det blev grönt. Nästa vecka händer det igen. Ett test som ger olika svar på samma kod är inte otur utan en skuld, och varje omkörning är en räntebetalning. Så här sätter ni flakiga tester i karantän, lagar orsaken med isolering och får tillbaka ett rött som betyder något.

Pull requesten är klar sedan lunch. Bygget blev rött på ett test som ingen i teamet har rört på ett halvår, så någon klickar på ”kör om”. Tjugo minuter senare är det grönt, och ingen tittar närmare på vad som hände. Nästa vecka blir samma test rött igen, i en annan pull request, och klicket sitter redan i ryggmärgen. **Ett test som ger olika svar på samma kod är inte otur. Det är en skuld, och varje omkörning är en räntebetalning.**

Flakiga tester är inget nytt problem. Martin Fowler skrev [Eradicating Non-Determinism in Tests](https://martinfowler.com/articles/nonDeterminism.html) redan 2011, och Google beskrev 2016 i [Flaky Tests at Google and How We Mitigate Them](https://testing.googleblog.com/2016/05/flaky-tests-at-google-and-how-we.html) hur det såg ut hos dem: runt 1,5 procent av alla testkörningar gav ett flakigt resultat, och nästan 16 procent av testerna var flakiga någon gång. Deras svar var inte att köra om tills det blev grönt. Det var att mäta, sätta i karantän och ta flakigheten ur vägen för alla andra.

## Omkörningen är det dyra, inte det röda

Ett rött bygge kostar några minuter. Ett bygge ingen litar på kostar hela tiden:

- **Rött slutar betyda något.** När tillräckligt många röda byggen visar sig vara flakes lär sig teamet att klicka ”kör om” innan de läser loggen. Den dagen ett riktigt fel dyker upp får det samma klick, och går vidare till main.
- **Väntetiden fördubblas.** En omkörning är en hel pipeline till. Det är den väntan som [Väntetidskalkylatorn](https://paperphyte.com/vantetidskalkylatorn) räknar på, och ett flakigt test lägger till den slumpmässigt, på de pull requests som råkade ha otur.
- **Sammanslagningen stannar.** Har ni en merge queue blockerar en flake inte bara sin egen pull request utan alla som står bakom den i kön. Har ni ingen kö mergar folk med rött och lovar att ”det var bara flaken”.
- **Felet ligger ofta i koden, inte i testet.** Ett test som ibland fallerar på en race condition har hittat en race condition. Den finns i produktion också, bara med andra tidsmarginaler. Omkörningen gömmer en bugg som testet faktiskt gjorde sitt jobb med.
- **Skulden växer tyst.** Ingen tar bort ett test som ”brukar gå”. Sviten växer, andelen flakiga tester med den, och till slut är hela sviten något man kör av gammal vana.

## Fem orsaker som står för det mesta

I vår erfarenhet går nästan alla flakiga tester att sortera i en handfull lådor:

- **Delat tillstånd.** Två tester skriver i samma databastabell, samma katalog eller samma globala variabel. Var för sig går de, i en viss ordning går de inte, och ordningen ändras när någon lägger till ett tredje test.
- **Tid.** En sleep på en halv sekund i stället för att vänta på ett tillstånd. Ett antagande om ”i dag” som går sönder vid midnatt, eller om tidszon som går sönder i CI. En timeout som räcker på en bärbar dator men inte på en liten CI-runner.
- **Samtidighet.** Testet startar något asynkront och kontrollerar resultatet innan det är klart. Oftast ligger felet i koden under test, ibland i själva testet, och ibland i testramverket.
- **Nätverk och externa tjänster.** Testet anropar ett riktigt API, en riktig DNS, en riktig klocka. Det som är utanför er kontroll kommer att vara utanför er kontroll vid fel tillfälle.
- **Resurser i CI.** Tester som körs parallellt på samma maskin slåss om portar, minne och diskutrymme. Testet var inte flakigt förrän någon slog på parallellism för att spara tid.

Ingen av lådorna rättas av en omkörning. Alla fem rättas av isolering: ett eget tillstånd, en egen klocka, en egen port, en egen container.

## Karantän: ut ur vägen, inte ut ur repot

Det som fungerar i praktiken är det Google beskrev: en karantän. Ett flakigt test slutar blockera, men slutar inte köras:

- **Upptäck automatiskt.** Ett test som både fallerat och lyckats på samma commit är flakigt per definition. Det behöver ingen människa avgöra. Pipelinen kan köra om ett fallerat test en gång, och om andra försöket lyckas är det en flake som ska registreras, inte ett godkänt test.
- **Flytta till karantän.** Testet körs fortfarande i varje bygge, men dess resultat påverkar inte om bygget är grönt. Det ger er data om hur ofta det fallerar utan att det stoppar någon.
- **Ge det en ägare och ett sista datum.** Samma regel som för [feature flags](https://paperphyte.com/ordlista/feature-flags): ingen karantän utan namn och deadline. Efter datumet är testet antingen lagat och tillbaka, eller borttaget med ett medvetet beslut.
- **Sätt ett tak.** Karantänen är ett väntrum, inte ett förråd. Bestäm hur många tester som får ligga där samtidigt. När taket nås lagas tester innan nya funktioner mergas. Det är så ni hindrar skulden från att växa.
- **Mät andelen.** Andelen flakiga körningar per vecka, på en graf som hela teamet ser. Siffran behöver inte vara noll. Den behöver gå åt rätt håll.

## Isolering är det som botar

Karantänen tar bort smärtan. Isolering tar bort orsaken:

- **Eget tillstånd per test.** En egen databas, ett eget schema eller åtminstone en transaktion som rullas tillbaka. En temporär katalog som testet själv skapar och tar bort. Inga globala variabler som lever vidare mellan tester.
- **Egen klocka.** Injicera tiden. Ett test som styr klockan kan testa midnatt, skottår och tidszoner när som helst, och är aldrig beroende av när det råkar köras.
- **Inget riktigt nätverk.** Stubba externa tjänster vid gränsen. Vill ni testa mot det riktiga API:et är det ett annat test, i en annan svit, som får vara rött utan att stoppa en merge.
- **Vänta på tillstånd, inte på tid.** Byt varje sleep mot en väntan på det ni faktiskt väntar på, med en timeout som är generös i CI. Testet blir både snabbare och stabilare.
- **En container per testfall när sviten är stor nog.** Det var så vi byggde testmiljön hos [DeLaval](https://paperphyte.com/uppdrag/delaval): varje testfall i en egen container, tusen tester parallellt, och feedback till utvecklaren på minuter i stället för timmar. Med en container per test finns inget delat tillstånd att slåss om. Ingen gemensam databas, inga portar som krockar, ingen ordning som spelar roll.

## Så börjar du

Det här kräver inget nytt verktyg. Det kräver att ni slutar betrakta omkörningen som en lösning:

1. Räkna. Ta de senaste veckornas byggen och lista testerna som både fallerat och lyckats på samma commit. Det är er karantänlista, och ni har förmodligen aldrig sett den samlad.
2. Slå på en automatisk omkörning av fallerade tester, en gång, och logga varje gång omkörningen räddade bygget. Omkörningen är en detektor, inte en lösning.
3. Inför karantänen i testramverket: en markering som gör att testet körs men inte räknas. De flesta ramverk har något sådant; annars är det en tagg och ett filter.
4. Ge varje test i karantän en ägare och ett datum, och sätt ett tak för hur många som får ligga där samtidigt.
5. Laga det värsta testet först. Det är sällan det mest komplicerade, det är det som fallerar oftast. Fråga vilken av de fem lådorna det hör till innan ni rör koden.
6. Mät andelen flakiga körningar varje vecka och visa den bredvid byggtiden. Båda är mått på hur mycket pipelinen går att lita på.

Det ni testade ska vara det ni driftsätter, skrev vi i [Bygg en gång](https://paperphyte.com/anteckningsbok/bygg-en-gang). Det förutsätter att ”testade” betyder något. Därför är det här en av de första sakerna vi tittar på i en [pipelinegenomgång](https://paperphyte.com/konsulttjanster/delivery-engineering): inte hur många tester ni har, utan hur många av dem ni litar på. En pipeline som ibland är röd utan anledning är en pipeline teamet redan slutat lyssna på, och då spelar resten av [Delivery Engineering](https://paperphyte.com/ordlista/delivery-engineering) mindre roll.

## Vårt korta svar

> Ett flakigt test är ett test som ger olika svar på samma kod, och en omkörning är ett sätt att slippa läsa svaret. Sätt det i karantän med ägare och sista datum, laga orsaken genom isolering, och mät andelen tills rött betyder fel igen.

Kör om när ni vet varför. Annars har ni bara flyttat felet till nästa vecka.

---

Det här är Markdown-versionen av ett inlägg i [Paperphytes anteckningsbok](https://paperphyte.com/anteckningsbok). Originalet finns på <https://paperphyte.com/anteckningsbok/flakiga-tester>. © Paperphyte AB. Ange källan med länk när du citerar eller sammanfattar texten.

Frågor om innehållet? [Kontakta Paperphyte](https://paperphyte.com/kontakt).
