
Ik dacht altijd dat mijn tests goed waren. Tot ik ze ging testen
Op de Dutch PHP Conference in 2016 kwam ik voor het eerst mutation testing tegen. Mijn eerste gedachte: dit gaat confronterend zijn voor mijn eigen werk. En dat was het ook. Maar juist die confrontatie leverde waardevolle lessen op waar iedere developer wat aan heeft.



Ik werkte al met automatische tests, zoals veel developers. Tests slagen en alles lijkt in orde. Maar in de praktijk blijken er toch situaties te zijn die ik niet had afgevangen. Dat maakte voor mij duidelijk hoeveel je eigenlijk op je tests vertrouwt.
Tests die slagen zijn nog niet altijd scherpe tests
Veel developers testen eerst of iets doet wat het moet doen. Logisch ook. Je begint vaak met de happy path: het scenario waarin alles klopt. De invoer is goed, de data is compleet en de gebruiker doet precies wat je verwacht.
Daarna voeg je uitzonderingen toe. Wat als een waarde ontbreekt? Wat als iets net anders is? Maar meestal niet allemaal.
Daar zit ook het risico. Want zolang je vooral de happy path test, weet je eigenlijk alleen dat het werkt als alles goed gaat. Niet wat er gebeurt als iets afwijkt.
Een test kan dus prima slagen, terwijl er nog steeds scenario’s zijn waar je geen rekening mee hebt gehouden. Dan heb je wel controle, maar nog geen volledige zekerheid. Zeker niet in code met veel voorwaarden, uitzonderingen of business rules.
Wat mutation testing doet
Mutation testing is geen test op zichzelf, maar een manier om je bestaande tests te controleren.
Het idee: je verandert bewust kleine stukjes van je code en kijkt wat er gebeurt. Kloppen je tests nog steeds, of merken ze dat er iets is veranderd?
Daarvoor gebruik je meestal een tool die dit automatisch doet. Voor PHP is dit bijvoorbeeld Infection. Zo’n tool maakt kleine aanpassingen in je code, bijvoorbeeld:
- een vergelijking net anders maken
- een voorwaarde omdraaien
- een regel tijdelijk verwijderen
Daarna draaien je tests opnieuw en stel je eigenlijk één vraag: merken mijn tests dat het gedrag is veranderd?
Als het antwoord nee is, dan weet je dat je test nog iets mist. Niet omdat de test slecht is, maar omdat hij blijkbaar nog niet scherp genoeg kijkt naar wat er echt belangrijk is.
Dat is voor mij de kern van mutation testing: je test niet alleen je code, maar ook hoe betrouwbaar je tests zelf zijn.
Wat je dan vindt
Vaak vind je een gat in je tests. Een scenario ontbreekt. Een randgeval is niet meegenomen. Of je test checkt wel dát er iets gebeurt, maar niet goed genoeg wát er precies moet gebeuren.
Soms wijst het terug naar je code. Dan blijkt niet de test het probleem, maar de logica zelf. Er zit bijvoorbeeld code in die weinig toevoegt, of een pad dat anders gemodelleerd had moeten worden.
Juist dat vind ik waardevol. Mutation testing geeft niet blind een oplossing, maar wel een scherp signaal. Het dwingt je om opnieuw te kijken: heb ik hier een betere test nodig, of begrijp ik mijn eigen code nog niet goed genoeg?
Werk je heel strikt volgens Test Driven Development, dan kan dit er anders uitzien. Je begint met een test en schrijft daarna alleen de code die nodig is om die test te laten slagen.
In zo’n werkwijze is de kans kleiner dat je iets over het hoofd ziet, omdat je stap voor stap vanuit gedrag bouwt.
Juist dan gebruik ik mutation testing vooral als controle: zijn mijn tests echt zo scherp als ik denk?
Vooral nuttig bij projecten met veel logica
Ik zou mutation testing niet op elk project loslaten. Het past vooral goed bij software waar veel logica in zit op kleine, afgebakende onderdelen. Denk aan systemen met veel business rules, validaties, beslisbomen en uitzonderingen. Daar werken unit tests vaak goed, en daar heeft mutation testing voor mij ook de meeste waarde.
Bij projecten die meer draaien om API-koppelingen of end-to-end flows ligt dat anders. Dan test je vaker op ketenniveau of procesniveau, en dan zit de grootste winst niet automatisch in mutation testing.
Ik zou het dus vooral overwegen bij software die lang mee moet, vaak doorontwikkeld wordt en veel regels bevat. Zeker ook als er gevoelige data in zit, of als een fout direct effect heeft op belangrijke acties of uitkomsten. Juist dan wil je zekerder weten of je tests echt doen wat je denkt dat ze doen. Dat sluit ook aan op hoe wij bij Linku naar software kijken: niet alleen iets bouwen dat vandaag werkt, maar iets maken dat onderhoudbaar en bruikbaar blijft.
Hoe ik het nu toepas
Ik gebruik het nu in een project waar veel specifieke logica in zit en waar unit tests al een belangrijk onderdeel van de werkwijze zijn. Juist daar kies ik ervoor om mutation testing toe te voegen, omdat kleine afwijkingen in logica daar snel grote gevolgen kunnen hebben. Dan helpt het om niet alleen te vragen of tests draaien, maar ook of ze echt scherp genoeg zijn.
Tegelijk pas ik het bewust niet overal toe. Er zijn ook projecten waar de testaanpak op een ander niveau ligt en waar deze methode minder toevoegt. Dat vind ik belangrijk om erbij te zeggen. Mutation testing is voor mij geen standaard stap, maar een gerichte keuze.
Waarom dit ook met AI relevant blijft
AI maakt het makkelijker om sneller code en tests te schrijven. Dat is handig, maar het onderliggende probleem verdwijnt daarmee niet. Je kunt sneller tests produceren zonder dat die tests automatisch beter nadenken over uitzonderingen, randgevallen of onbedoeld gedrag.
Misschien wordt dat probleem zelfs groter. Want hoe makkelijker het wordt om veel code en veel tests te maken, hoe groter ook de kans dat je denkt dat alles wel goed zit. Voor mij maakt AI mutation testing daarom niet minder relevant, maar juist interessanter. Het helpt om die extra kritische stap te zetten.
Wat ik vooral wil meegeven
Voor mij gaat mutation testing uiteindelijk niet alleen over een tool of een techniek. Het raakt aan iets groters. Namelijk het besef dat ook een test een aanname is. Ook een test kan iets missen. Ook een test kan te smal kijken naar wat kwaliteit eigenlijk betekent.
Werk je heel strikt volgens Test Driven Development, dan begin je altijd met een test en schrijf je daarna alleen de code die nodig is om die test te laten slagen.
Dat is voor mij de echte waarde. Niet nog een vinkje in je pipeline, maar beter begrijpen wat je tests echt afdekken, en wat ze misschien nog missen.

