Expertise hub / Betrouwbaarheid
Betrouwbaarheid 4 min lezen

Wat zijn flaky tests en hoe los je ze op?

Je suite staat op rood, maar niemand kijkt er nog naar om. Dat moment waarop het team besluit het te negeren, is het échte probleem.

Iedereen kent het scenario. De build faalt. Iemand kijkt, haalt de schouders op, en drukt op "rerun". De tweede keer slaagt hij wel. Probleem "opgelost".

Dat moment waarop het team besluit dat rood niet meer betekent dat er iets stuk is, dat is het echte probleem. Niet de falende test. De gewenning eraan.

Wat is een flaky test?

Een flaky test is een test die soms slaagt en soms faalt, zonder dat de code veranderde. Zelfde input, zelfde omgeving, ander resultaat. Hij detecteert niet altijd hetzelfde gedrag. En dat maakt hem gevaarlijker dan een test die consequent faalt.

Een kapotte test kun je fixen. Een onbetrouwbare test ondermijnt iets fundamentelers: het vertrouwen in je hele suite. Want als deze test soms liegt, welke andere doen dat dan ook?

Een test die je niet vertrouwt, is geen test. Het is ruis met een groen vinkje als het meezit.

Het echte gevaar

Flaky tests wekken een vals gevoel van veiligheid. Je suite is groen, dus alles is in orde. Behalve dat een deel van dat groen toeval is. En het omgekeerde is nog erger: teams leren om rood te negeren. "Ah, die is gewoon flaky." Tot de dag dat rood écht rood was.

Wij zien bij klanten hoe dit sluipend gaat. Eerst is het één test. Dan drie. Dan is er een gedeeld begrip in het team dat "de suite altijd wat rood staat". Op dat punt is je vangnet geen vangnet meer, maar decoratie.

De vijf oorzaken

Timing

De klassieker. De test klikt op een knop voordat de pagina klaar is met laden. Op een snelle machine gaat het goed, op een trage CI-runner niet. Vaste wachttijden (sleep(2)) zijn een pleister die op een dag loslaat.

Externe afhankelijkheden

JJe test is afhankelijk van systemen die buiten de controle van de test liggen: een externe API, een service van een andere applicatie of een gedeelde omgeving. Die is even traag, even down, of geeft net iets anders terug. Je test faalt, maar je code is prima.

Gedeelde testdata

Twee tests gebruiken hetzelfde record. De ene wijzigt het, de andere leest het. Draaien ze parallel, dan is de uitkomst een gok. Draaien ze in een andere volgorde, idem.

Onbetrouwbare omgevingen

De testomgeving is net niet gelijk aan productie. Er draait nog iets van gisteren. De cache is niet leeg. De ene runner heeft meer geheugen dan de andere.

Niet-deterministische logica

De test hangt af van de huidige tijd, willekeurige gegevens of de volgorde waarin tests worden uitgevoerd. Daardoor kan exact dezelfde test verschillende resultaten geven.

Hoe je ze oplost

Het verschil tussen de twee zit in een paar regels code:

checkout.spec.tsPlaywright
// flaky: gokt hoelang laden duurt
await page.click('#submit');
await page.waitForTimeout(2000);
await expect(page.locator('#confirmation')).toBeVisible();

// stabiel: wacht op de conditie zelf, niet op een gok
await page.click('#submit');
await expect(page.locator('#confirmation')).toBeVisible({ timeout: 10000 });

Op een snelle machine zie je het verschil niet. Op een drukke CI-runner, tijdens honderd parallelle builds, wel — en precies dan wil je dat je test wacht op wat er echt gebeurt, niet op een aanname.

De houding die het verschil maakt

Het belangrijkste is geen techniek, het is een mentaliteitswijziging: behandel een flaky test als een bug. Niet als achtergrondruis, niet als "die doet dat soms". Zet hem op de backlog, geef hem een prioriteit, en fix hem.

Teams die dat doen, hebben een suite waar rood ook echt rood betekent. En dat is uiteindelijk het enige waar het om gaat.

// Verder praten

Herkenbaar?

We nemen je testaanpak door en zeggen eerlijk waar de winst zit. En waar niet.

Plan een gesprek
// Lees ook