Waarom slimme testers niet het midden testen, maar de randen
Stel je voor: je test een formulier voor een verzekering. Leeftijd moet tussen 18 en 65 zijn. Welke waarden zou jij invoeren?
Als je nu denkt aan 25, 40 of 50 (willekeurige getallen ergens in het midden) dan ben je niet de enige. Maar hier is het probleem: met die aanpak mis je waarschijnlijk de meeste bugs.
Bugs verstoppen zich namelijk zelden in het midden. Ze zitten op de grenzen. En precies daar richt boundary value analysis (BVA) zich op.
Wat is boundary value analysis?
BVA is een testtechniek die systematisch de grenzen van invoerbereiken test, plus de waarden net erbinnen en net erbuiten. Klinkt simpel, en dat is het ook. Maar die eenvoud is precies wat het zo effectief maakt.
Neem dat leeftijdsveld van 18-65. Met BVA test je zes waarden: 17, 18, 19, 64, 65 en 66. Dat is alles. Zes tests voor volledige grensdekking.
Wanneer gebruik je BVA?
BVA werkt het beste wanneer je te maken hebt met duidelijke grenzen. Denk aan:
- Leeftijdsrestricties: minimaal 18 jaar, maximaal 65 jaar
- Prijsbereiken: van 0 tot 999 euro
- Datumbereiken: boekingen maximaal 90 dagen vooruit
- Tekstlengtes: gebruikersnaam maximaal 20 tekens
- Bestandsgroottes: upload maximaal 5 MB
- API parameters: limit, offset, page size
Geen duidelijke min/max? Dan is equivalence partitioning vaak een betere keuze.
Waarom zitten bugs op de grenzen?
Onderzoek toont aan dat een groot deel van input validation bugs zich op grenswaarden bevindt. Dat klinkt misschien verrassend, maar het wordt logisch zodra je naar de code kijkt.
Off-by-one errors
Dit is de klassieke ‘eentje-ernaast-fout’. Het verschil tussen if (age <= 65) en if (age < 65) is slechts één karakter. Maar de impact is groot: in het eerste geval wordt 65 geaccepteerd, in het tweede niet. Test je met waarde 40? Je merkt niets. Test je met 65? Bug gevonden.
Vergeten grenzen
Soms vergeet een developer simpelweg een grens te implementeren:
if (age >= 18): accept # Waar is de maximum check?
Deze code accepteert vrolijk een leeftijd van 999. Door te testen met 66 ontdek je dit meteen.
Efficiëntie
Zonder BVA zou je misschien tientallen willekeurige waarden testen (20, 30, 40, 55) zonder ooit een boundary bug te vinden. Met BVA test je zes waarden en heb je volledige grensafdekking. Maximale bugdetectie met minimale inspanning.
Een praktijkvoorbeeld uitgewerkt
De requirement luidt: “Het leeftijdsveld accepteert waarden van 18 tot en met 65 jaar.”
Dit zijn je zes testwaarden:
| Waarde | Positie | Verwacht | Wat je checkt |
|---|---|---|---|
| 17 | Onder minimum | Afwijzen | Werkt de ondergrens? |
| 18 | Op minimum | Accepteren | Is minimum inclusief? |
| 19 | Net boven minimum | Accepteren | Geen off-by-one bij min? |
| 64 | Net onder maximum | Accepteren | Geen off-by-one bij max? |
| 65 | Op maximum | Accepteren | Is maximum inclusief? |
| 66 | Boven maximum | Afwijzen | Werkt de bovengrens? |
Stel dat de developer per ongeluk if (age > 18) heeft geschreven in plaats van if (age >= 18). Dan wordt waarde 18 afgewezen terwijl die geaccepteerd had moeten worden. Bug gevonden.
BVA toepassen in vijf stappen
Stap 1: Identificeer de grenzen
Zoek in je requirements naar minimum- en maximumwaarden. “Leeftijd 18-65” geeft je twee grenzen. “Gebruikersnaam maximaal 20 tekens” ook: 0 (leeg) en 20.
Stap 2: Test de grenzen zelf
Test de grenswaarden: 18 en 65. Bepaal of ze inclusief of exclusief zijn. “18-65” betekent meestal inclusief, maar “tot 65 jaar” kan exclusief zijn.
Stap 3: Test net buiten de grenzen
Test 17 en 66. Beide moeten worden afgewezen. Worden ze toch geaccepteerd? Bug gevonden.
Stap 4: Test net binnen de grenzen
Test 19 en 64. Beide moeten worden geaccepteerd. Dit vangt off-by-one errors op.
Stap 5: Documenteer je tests
Test: Leeftijd = 17 → Verwacht: Foutmelding "Minimaal 18 jaar"
Test: Leeftijd = 18 → Verwacht: Geaccepteerd
Test: Leeftijd = 19 → Verwacht: Geaccepteerd
...
De BVA-formule
Voor elk bereik [minimum, maximum] test je:
- minimum – 1 (net erbuiten)
- minimum (de grens zelf)
- minimum + 1 (net erbinnen)
- maximum – 1 (net erbinnen)
- maximum (de grens zelf)
- maximum + 1 (net erbuiten)
Zes tests = volledige boundary coverage.
Weinig tijd? In de praktijk kun je ook met vier waarden werken: min-1, min, max, max+1. Je slaat dan de “net binnen” waarden over. Minder grondig, maar vaak voldoende voor snelle checks.
Waar gaat het vaak mis?
Alleen de grenzen testen, niet erbuiten
Je test 18 en 65, maar niet 17 en 66. Het probleem: je weet dan niet of de grenzen echt werken. Misschien wordt alles boven de 10 geaccepteerd, maar dat zou je niet merken.
Alleen geldige waarden testen
Je test 18, 19, 64 en 65, maar geen ongeldige waarden. Dan mis je bugs in de foutafhandeling. Wat gebeurt er als iemand 17 invoert? Nette foutmelding of crash?
Goed om aan te denken
Naast de klassieke valkuilen zijn er scenario’s die makkelijk over het hoofd worden gezien:
Floating point grenzen
Prijzen en percentages zijn verraderlijk. Bij een prijs van €0-€999.99: test je €999.98, €999.99 en €1000.00? Afrondingsfouten zitten precies op die grenzen. Test altijd met de exacte grenswaarde én met waarden die er net boven en onder liggen.
Null en lege waarden
Wat als een gebruiker niets invult? Een leeg veld is ook een boundary. Test altijd: null (geen waarde), leeg (lege string) en alleen spaties. Dit zijn de waarden waar veel validatielogica op crasht.
Datumgrenzen
Datums hebben lastige grenzen: 28 of 29 februari (schrikkeljaren), het verschil tussen maanden van 30 en 31 dagen, en jaarovergangen. Test deze expliciet bij boekingen, termijnen en verloopdatums.
Frontend én backend
Je test het formulier in de browser. De UI blokkeert waarden boven 65. Klaar? Nee. De API moet dezelfde validatie hebben. Test boundaries zowel via de UI als rechtstreeks tegen de API. Ze moeten hetzelfde gedrag vertonen.
BVA bij API’s
Boundaries zijn niet alleen voor formulieren. Neem een endpoint met paginering:
GET /api/users?limit=10&offset=0
Voor de limit parameter test je: 0 (vaak niet toegestaan), 1 (net boven minimum), 100 (maximum) en 101 (net erboven). Voor offset: 0 (begin), -1 (moet falen), en waarden rond het totaal aantal records. API boundaries worden vaak vergeten omdat je ze niet “ziet” in een interface.
BVA versus equivalence partitioning
Beide zijn black-box testtechnieken, maar ze vullen elkaar aan.
Equivalence partitioning verdeelt mogelijke invoer in groepen en test één representatieve waarde per groep. Voor leeftijd 18-65 krijg je drie tests: 10 (te jong), 40 (geldig), 70 (te oud).
BVA gaat dieper op de grenzen: 17, 18, 19, 64, 65, 66.
Combineer je beide, dan heb je zeven unieke testwaarden die zowel de partities als de grenzen afdekken. EP voor brede dekking, BVA voor diepe dekking op de grenzen.
ISTQB en tools
BVA is onderdeel van de ISTQB Foundation Level syllabus. Je moet grenzen kunnen identificeren, de formule toepassen, en het verschil met equivalence partitioning uitleggen. In de Advanced syllabus komen ook 2-value en 3-value boundary testing aan bod.
Tools die helpen:
- UI testing: Playwright, Cypress (modern en makkelijk te combineren met data-driven testing)
- API testing: Postman voor handmatige tests, Hypothesis (Python) voor automatische boundary-generatie
- Testdata: Mockaroo voor het genereren van edge cases
Samengevat
De kernformule: voor elk bereik test je zes waarden rond de grenzen. Die zes tests vinden meer bugs dan tientallen willekeurige tests in het midden.
Denk ook aan floating point waarden, null/lege invoer en API’s. Ook die hebben grenzen. En test altijd zowel frontend als backend.
De volgende keer dat je een invoerveld moet testen, vraag jezelf af: wat zijn de grenzen? Test die grenzen, plus de waarden net erbinnen en erbuiten. Je zult versteld staan van wat je vindt.