Blogserie geautomatiseerd testen deel 5: De testpiramide

donderdag 1 maart 2018

In aflevering 3 van deze blogserie hebben we álle voor- en nadelen van geautomatiseerd testen op een rijtje gezet. En in aflevering 4 de situaties die zich er wel of juist niet goed voor lenen. Na die voorbereidende bewegingen wordt het tijd voor het model dat zo’n vaste plaats heeft verworven: de testautomatiseringspiramide, kortweg de testpiramide. Alle modellen zijn goed (of fout), sommige modellen zijn handig. De testpiramide is zo’n handig model bij het uitleggen van de belangrijkste principes van geautomatiseerd testen.

Kies je technische scope

Geautomatiseerd testen begint met een oud maar nog steeds belangrijk inzicht, namelijk dat testen zich afspeelt op verschillende interactieniveaus, van het technische perspectief tot het perspectief van de eindgebruiker. Op elk niveau kun je ervoor kiezen om wel of niet te automatiseren en de manier van automatiseren is per niveau verschillend. Het is dus van doorslaggevend belang dat je je bewust bent van het niveau waarop je wilt automatiseren. De testpiramide die je hieronder ziet helpt daarbij. In deze blog pak ik graag door op de inzichten van Mike Cohn die je onder andere hier kunt vinden.

Automatiseren op GUI-, API- of unit niveau

De eerste boodschap van de testpiramide is dat je geautomatiseerd testen op drie wezenlijk verschillende niveaus kunt oppakken: via de Graphical User Interface (GUI), via de Application Program Interface (API) of op het laagste niveau van de software units.

Daar moet je dus over nadenken: Op welk niveau ga ik beginnen? Welk niveau laat ik (vooralsnog) liggen? Wie doet wat?

In de figuur zijn de drie niveaus genummerd. Bij het bepalen van je strategie hanteer je de drie bijbehorende principes, die aansluiten bij de drie niveaus van de piramide:

1. Test vroeg en veel op unit niveau
2. Doe je integratietesten op API service niveau
3. Automatiseer niet teveel via de GUI

Hieronder volgt een verdere toelichting op deze drie principes.

1. Test vroeg en veel op unit niveau

Een in het oog springende eigenschap van een piramide is dat de onderkant het breedst is. Dat past mooi, want investeren in het onderste niveau levert niet alleen de gewenste snelle feedback (hoe vroeger je een fout vindt hoe beter) maar is ook sneller, stabieler en beter onderhoudbaar. Zeker op de lange termijn is het daarmee goedkoper dan testen op de hogere niveaus. Mits je hier een gedisciplineerde ‘Way of Work’ van maakt: code is alleen ‘done’ als de scripts én worden meegeleverd én adequate technische en functionele dekking bieden. Liefst als onderdeel van een Test Driven Development (TDD) en Continuous Integration (CI) framework. Dit is de stevige basis van de testpiramide.

2. Doe je integratietesten op API service niveau

We testen hier het berichtenverkeer van en naar de applicatie, via de machine-machine interface en niet via de mens-machine interface. Bijvoorbeeld: ‘doe mij de postcode van Orteliuslaan 1000, Utrecht’, of ‘bereken voor mij de maandpremie van een polis met die en die karakteristieken’. Of ‘stuur me in XML-formaat de koersontwikkeling van de bitcoin van afgelopen week’. Meestal zijn dit gestandaardiseerde ‘services’ met standaard (SOAP of REST) protocollen en gestandaardiseerde (XML of JSON) dataformaten. Als deze services via het internet lopen noemen we ze ‘webservices’.

Het is inmiddels een breed geaccepteerd inzicht dat testen via de service laag (API testen) robuuster is dan via de GUI. Wijzigingen in de schermen zoals de plaatsing van velden of wijzigingen in de technische karakteristieken van schermelementen hebben namelijk geen invloed op dit soort API testen. Dat maakt de scripts stabiel, toekomstvast en beter onderhoudbaar. En meestal ook vele malen sneller dan via de GUI. Daarom automatiseren we de systeem- en ketenintegratietesten liever op het niveau van berichtenverkeer, zowel tussen de functies binnen de applicatie als naar buiten met aanpalende systemen.

3. Automatiseer zo min mogelijk via de GUI

Geautomatiseerd testen via de GUI lijkt ideaal, want het dekt het complete systeem (de hele ‘technology stack’), lijkt het meest op handmatig testen, staat het dichtst bij de eindgebruiker en benadert de werkelijkheid het beste. De in aflevering 1 genoemde ‘knuffelfactor’ is hier extra van toepassing; de aanblik van een test die je op de echte schermen voor je ogen automatisch ziet afspelen heeft iets magisch.

Dat zijn allemaal niet te onderschatten voordelen, maar er is ook een andere kant: testen via de GUI is kwetsbaar en onderhoudsintensief. Want aanpassingen in de GUI-schil leiden al snel tot falende scripts. Verder kan de analyse van gevonden fouten lastig en tijdrovend zijn omdat problemen op elk niveau ‘in de stack’ kunnen zitten. Tenslotte is de trage synchronisatie via de GUI vaak een probleem. De scripts zijn afhankelijk van de snelheid van de server en de paginaopbouw en soms moet je (lange) wachttijden inbouwen, om er zeker van te zijn dat het script niet harder loopt dan het te testen systeem. Dat maakt de scripts trager dan je zou verwachten.

Tot zover de boodschap van de testpiramide in een notendop. Ik zou hem bijzonder serieus nemen!

En nog even dit: de testpiramide naast het V-model

Het is altijd fijn om twee ogenschijnlijk verschillende benaderingen onder één noemer te brengen in een ‘grand unifying theory’. Zeker als we daarmee een brug slaan tussen het goede van klassiek gestructureerd testen en nieuwe inzichten en modellen anno nu. OK, daar komt ‘ie:

Je kunt de testpiramide en het V-model natuurlijk niet aan elkaar gelijkstellen want er zijn allerlei verschillen in doel en boodschap. Er is dus geen 1:1 relatie, maar in bijgaande figuur zie je wel de analogie in de drie lagen. Ook in de testpiramide zie je de testsoorten van het klassieke V-model en W-model: unit testen onderaan en de E2E acceptatietesten die meestal via de GUI verlopen bovenaan. En er tussenin de systeem- en integratietesten, die weliswaar ook via de GUI kunnen maar waar we vooral focussen op de interfaces en het berichtenverkeer tussen de deelsystemen.

Tot zover mijn brugje tussen oude en nieuwe inzichten, die soms minder ver van elkaar staan dan weleens wordt gesuggereerd.

Volgende keer: Hoe ‘praat’ een testtool met de applicatie?