Kennisbank
Architectuur 7 min leestijd

Teststrategie voor maatwerk en SaaS.

Welke tests wanneer: unit, integratie of E2E? Over de testpiramide, pragmatisme en waarom 100% coverage een slecht doel is.

Waarom testen?

Automatische tests zijn geen doel op zich. Ze zijn een middel om drie dingen te bereiken die direct invloed hebben op de snelheid en betrouwbaarheid van je softwareontwikkeling.

Vertrouwen om te deployen. Als je testsuite groen is, weet je dat de applicatie werkt zoals verwacht. Je hoeft niet handmatig door twintig schermen te klikken voor elke release. Je drukt op de knop en het gaat live. Dat vertrouwen is het verschil tussen dagelijks deployen en maandenlang uitstellen uit angst.

Vertrouwen om te refactoren. Code moet kunnen veranderen. Requirements veranderen, inzichten veranderen, technologie verandert. Zonder tests durf je bestaande code niet aan te passen, waardoor technische schuld zich opstapelt. Met tests kun je vrijelijk herstructureren en weet je binnen seconden of je iets hebt gebroken.

Documentatie van verwacht gedrag. Een goed geschreven test vertelt exact wat de applicatie hoort te doen. Niet wat een developer zes maanden geleden dacht dat het moest doen, maar wat het nu daadwerkelijk doet. Tests zijn levende documentatie die altijd up-to-date is — in tegenstelling tot een wiki die na twee weken verouderd is.

Wat tests nadrukkelijk niet zijn: een wedstrijd om 100% code coverage te halen. Coverage is een vanity metric. Je kunt 100% coverage hebben met tests die niets nuttigs valideren. En je kunt 70% coverage hebben met tests die elk kritiek pad afdekken. Het gaat om de juiste tests, niet om de meeste tests.

De testpiramide

De testpiramide is een model dat beschrijft hoe je je teststrategie opbouwt. De basis is breed, de top is smal. Dat is geen toeval — het weerspiegelt de verhouding tussen snelheid, kosten en betrouwbaarheid.

Onderin: unit tests. Snel, geisoleerd en goedkoop. Een unit test valideert een enkel stuk logica zonder afhankelijkheden van databases, API's of externe services. Je hebt er honderden en ze draaien in seconden. Ze zijn de basis van je teststrategie.

Midden: integratietests. Testen dat componenten samenwerken. Een integratietest raakt de database, stuurt een HTTP-request of controleert dat een service correct communiceert met een andere service. Langzamer dan unit tests, maar ze vangen problemen die unit tests missen — zoals een foutieve query of een verkeerde API-response.

Bovenin: E2E tests. End-to-end tests simuleren een volledige gebruikersflow in de browser. Ze zijn traag, duur in onderhoud en broos. Maar voor de meest kritieke paden — denk aan het afrekenproces van een webshop — zijn ze onmisbaar.

De piramidevorm is essentieel. Als je meer E2E tests dan unit tests hebt, heb je een omgekeerde piramide: een testsuite die traag is, vaak breekt en meer onderhoud kost dan de code die het test. Veel unit tests, een gezonde laag integratietests en een handvol E2E tests voor de kritieke paden — dat is de balans.

Tests schrijf je niet om te bewijzen dat je code werkt. Je schrijft ze zodat je het durft te veranderen.

Unit tests in Laravel

Unit tests in Laravel testen businesslogica in isolatie. Geen database, geen HTTP-requests, geen framework-boilerplate. Puur de logica die jouw applicatie uniek maakt.

Denk aan een prijscalculator die kortingen berekent op basis van volume, klanttype en actieve promoties. Die logica bevat tientallen edge cases: wat als de korting hoger is dan de prijs? Wat als twee promoties overlappen? Wat als het volume exact op de grens van een staffelkorting zit? Dit zijn tests die in milliseconden draaien en die je met vertrouwen honderd scenario's laten doorlopen.

De feedback loop is kort. Je wijzigt een berekening, draait de tests en weet binnen twee seconden of alles nog klopt. Dat maakt unit tests ideaal tijdens het ontwikkelen: je schrijft de test, ziet hem falen, schrijft de code en ziet hem slagen.

Een veelgemaakte fout is te veel mocken. Als je voor een unit test zes dependencies moet mocken, test je waarschijnlijk het verkeerde. Dat is een signaal dat de class te veel verantwoordelijkheden heeft, niet dat je meer mocks nodig hebt. Mock alleen externe afhankelijkheden die je niet wilt aanroepen — een betaalprovider, een e-mailservice. Interne logica test je met echte objecten.

Integratietests

Integratietests zijn voor de meeste Laravel-applicaties de sweet spot. Ze testen dat je componenten correct samenwerken: controllers die de juiste responses geven, services die data correct opslaan, events die de juiste listeners triggeren.

Laravel maakt integratietesten bijzonder toegankelijk. Met de ingebouwde HTTP-testmethodes kun je een volledige request simuleren en de response valideren — van statuscode tot JSON-structuur tot database-state. Je test het hele pad van request tot response zonder een browser te openen.

Database-interacties zijn een belangrijk onderdeel. Wordt de order correct opgeslagen met de juiste status? Wordt de voorraad bijgewerkt na een bestelling? Wordt een gebruiker correct gekoppeld aan een organisatie? Dit zijn vragen die unit tests niet beantwoorden omdat ze de database niet raken, maar die cruciaal zijn voor de werking van je applicatie.

API-endpoint tests vallen ook in deze categorie. Je valideert dat endpoints de juiste data teruggeven, dat authenticatie werkt, dat validatie foutieve input afwijst en dat autorisatie voorkomt dat gebruikers bij data komen die niet van hen is. Dit zijn tests die direct aansluiten bij de functionaliteit die je gebruikers ervaren.

Voor de meeste maatwerk- en SaaS-applicaties vormen integratietests de ruggengraat van de testsuite. Ze zijn snel genoeg om bij elke commit te draaien, maar breed genoeg om echte problemen te vangen.

E2E tests

End-to-end tests openen een echte browser, klikken op knoppen, vullen formulieren in en verifieren dat het resultaat klopt. Ze testen wat de gebruiker ervaart, inclusief JavaScript-interacties, redirects en visuele feedback.

De kracht van E2E tests zit in hun realisme. Ze vangen problemen die geen andere test vangt: een formulier dat niet submit door een JavaScript-fout, een redirect-loop na het inloggen, een betaalflow die halverwege vastloopt. Voor kritieke gebruikersstromen — registratie, betaling, onboarding — is dat onmisbaar.

De keerzijde is de prijs. E2E tests zijn traag: een suite van honderd tests kan tien minuten of langer duren. Ze zijn broos: een kleine wijziging in de UI kan tientallen tests laten falen. En ze zijn duur in onderhoud: elke aanpassing aan de interface vereist updates in de tests.

Daarom reserveer je E2E tests voor de paden die er het meest toe doen. Het registratieproces. De betaalflow. Het aanmaken van de belangrijkste entiteit in je applicatie. Als deze paden werken, werkt het hart van je product. De rest dek je af met unit- en integratietests.

Een test die je niet durft te vertrouwen, is erger dan geen test. Dan heb je onderhoudslast zonder zekerheid.

Pragmatische teststrategie

De perfecte testsuite bestaat niet. Wat wel bestaat is een pragmatische strategie die maximale zekerheid geeft met minimale overhead. Dit zijn de principes die wij hanteren:

Test het happy path en de edge cases die ertoe doen. Niet elk denkbaar scenario hoeft een test. Focus op de flows die je gebruikers daadwerkelijk doorlopen en op de randgevallen die serieuze gevolgen hebben als ze falen — een dubbele betaling, dataverlies, een beveiligingslek.

Focus op business-kritieke flows. De prijsberekening van je SaaS moet kloppen. De facturatie moet correct zijn. Gebruikersrechten moeten werken. Begin daar. De kleur van een knop hoeft geen test.

Nieuwe bug? Eerst een test, dan de fix. Als een bug in productie opduikt, schrijf je eerst een test die het probleem reproduceert. Dan fix je de bug. De test bewijst dat de fix werkt en voorkomt dat dezelfde bug ooit terugkomt. Dit is een van de meest waardevolle gewoontes in softwareontwikkeling.

Tests moeten slagen voor deployment. Geen uitzonderingen. Als de CI/CD-pipeline rood is, gaat er niets live. Dit klinkt streng maar het voorkomt de situatie waarin "we fixen het later" leidt tot een productieomgeving vol bekende bugs.

Test geen framework-code. De authenticatie, validatie en database-laag van Laravel zijn al uitgebreid getest door het Laravel-team en duizenden gebruikers wereldwijd. Test niet of standaard framework-functionaliteit werkt. Test de logica die jouw applicatie uniek maakt.

Conclusie

Een goede teststrategie draait niet om maximale coverage of de nieuwste testtools. Het draait om vertrouwen: vertrouwen dat je kunt deployen, vertrouwen dat je kunt refactoren, vertrouwen dat je product doet wat het belooft.

De testpiramide geeft je de structuur: veel unit tests voor snelle feedback, een gezonde laag integratietests voor samenwerking tussen componenten, en een selecte set E2E tests voor de kritieke gebruikersstromen. Voeg daar pragmatische principes aan toe — test wat ertoe doet, niet wat makkelijk te testen is — en je hebt een strategie die meeschaalt met je product.

Wil je weten hoe jouw applicatie er qua teststrategie voor staat? Wij helpen je graag met een assessment en een plan om je testsuite naar het juiste niveau te brengen.

Onderwerpen
Testing Unit Tests E2E Laravel Kwaliteit

/Hulp nodig?

Vragen over dit onderwerp? Laten we het erover hebben.

Neem contact op