Kwaliteit en stabiliteit staan voorop
Automatisch testen is een uitstekende manier om kwaliteit en stabiliteit van onze producten doorlopend te waarborgen, maar we doen natuurlijk veel méér dan dat. Hierbij kun je onder meer denken aan het volgende:
1. OTAP
Door elk stukje code door verschillende omgevingen – ontwikkeling, test, acceptatie en productie – te ‘halen’, hebben we een grote zekerheid dat het werkt zoals het is bedoeld. Hieronder vallen onder andere het testen op een testomgeving en de acceptatietests door de klant.
2. Code quality
We maken gebruik van een coding standard (CS) om te voorkomen dat iedereen zijn eigen stijl hanteert. Daarnaast passen we static analysis toe om bronnen van mogelijke problemen (lees: slecht geschreven code) op te sporen. De code wordt gecontroleerd op fouten en in geval van issues krijgen we een waarschuwing. Dit is niet echt een test, maar het draagt uiteraard wél bij aan de kwaliteit.
3. Pentesten en vulnerabilities
Deze worden soms uitgevoerd door onze eigen DevOps engineers, maar meestal laten we dit over aan een externe partij, waarna wij met de resultaten aan de slag gaan. Ook monitoren we onze projecten op zogenaamde vulnerabilities in gebruikte packages.
4. End-to-end testen
End-to-end testen voeren we uit in een draaiende omgeving. Deze testen geven inzicht in de samenhang tussen de verschillende processen, systemen en data bij normaal gebruik, maar ook onder bijzondere omstandigheden.
5. Live monitoring
Sommige aspecten van een webapplicatie – bijvoorbeeld of een achtergrondproces of koppeling nog goed draait na een aanpassing – kun je niet controleren op het moment dat de code wordt aangepast. Daarom monitoren we dit live.
6. Error tracking
In een live omgeving zien wij dezelfde rare foutmeldingen die een klant bijvoorbeeld kan krijgen als hij probeert in te loggen. Dankzij error tracking hebben we zo’n bug vaak al gerepareerd voordat de klant een service ticket heeft kunnen inschieten.
7. Performance tests
Bij zowel webapplicaties als websites richten we ons meer en meer op performance tests. Zo kunnen we bijvoorbeeld de laadtijd van de homepage bewaken en controleren of formulieren die belangrijk zijn voor conversies goed werken. Dat is niet alleen handig bij de ontwikkeling van de website, maar ook na het doorvoeren van aanpassingen.
8. Kubernetes
Bij de ontwikkeling van webapplicaties, websites en webshops maken we gebruiken van Kubernetes: een open source orkestratiesysteem voor het beheren van gedistribueerde applicaties uit containers. Dit maakt het mogelijk snel verschillende omgevingen op te tuigen waardoor we onder andere flexibeler kunnen testen en meer controle hebben over een nieuw te releasen versie.
LEESTIP | DevOps engineer Martin schreef hier eerder een blog over. Zeker de moeite waard om ook even te lezen!
9. Renovate bots
Onze projecten maken gebruik van packages die onderhouden moeten worden. We hebben zogenaamde “renovate runners” ingericht die deze packages periodiek geautomatiseerd bijwerken of duiden op conflicten met nieuwe versies die opgelost moeten worden om het project up-to-date te houden.
Automatisch testen tijdens realisatie
Bij het ontwikkelen en aanpassen van webapplicaties maken we gebruik van een gestandaardiseerde basis waarin een lokale testbasis met standaard pipeline-integratie is opgenomen. Dit betekent dat na elke wijziging standaard alle tests worden uitgevoerd en dat je pas kunt deployen nadat alle tests zijn geslaagd.
Gescheiden tests
Voorheen werden nagenoeg alle automatische tests (inclusief functionele en end-to-end tests) voor webapplicaties opgezet door onze back-enders. Nu we steeds meer overschakelen naar Single Page Applications (SPA’s) waarbij we een API first aanpak hanteren, is de frontend vaker een applicatie op zich en bevat deze vaak business rules en complexe functionaliteit. Een goede ontwikkeling, omdat je een kwalitatief beter product kunt leveren. Dit heeft er wel toe geleid dat een front-end developer meer tijd kwijt is aan het schrijven van (voornamelijk end-to-end) tests.
Back-end
Back-enders houden zich met name bezig met het schrijven van functionele tests, bedoeld voor het testen van bijvoorbeeld API endpoints. In tegenstelling tot unit tests wordt een endpoint van voor tot achter getest. Kortom: je test vooral de samenhang tussen de onderdelen en of wat naar de gebruiker of front-end gestuurd wordt voldoet aan de verwachtingen of een bepaald scenario. Deze tests zijn relatief traag, omdat ze veel omhelzen.
Daarnaast schrijven back-enders unit tests om kritieke onderdelen op detailniveau te testen. Unit tests zijn vooral geschikt voor complexere componenten met veel mogelijke variaties. Bijvoorbeeld een component dat berekeningen uitvoert op basis van verschillende parameters. Deze tests zijn erg snel uit te voeren.
Front-end
Front-end developers schrijven ook unit tests, maar houden zich voornamelijk bezig met end-to-end testen. Met behulp van het framework Cypress testen onze front-enders vanuit een browser hun Vue implementatie. Dit lijkt erg veel op functioneel testen, maar hierbij wordt een browser en interactie, zoals muisklikken of een selectie maken in een dropdown, gesimuleerd.
Samen scenario’s uitwerken
Testen is tegenwoordig een multidisciplinaire aangelegenheid. Daarom is het nóg belangrijker dan voorheen om goed met elkaar te overleggen om dubbel testen of testhiaten te voorkomen. De front-ender, back-ender en tester bekijken samen de user stories om te bedenken welke scenario’s getest moeten worden om tot een goede dekking te komen en welke testdata (ook wel fixtures genoemd) daarbij nodig is. De tester denkt mee vanuit een testplan en de klant kan eventueel ondersteunen door aan te geven wat voor hem kritische onderdelen zijn en input in de vorm van representatieve data of domeinkennis aan te leveren.
De initiële set van testdata is erg belangrijk, omdat deze wordt gebruikt voor het tonen van een volledig werkende staging omgeving waar een gebruiker doorheen kan klikken en dient als uitgangspunt voor de testscenario’s die back-end (functioneel) en front-end (end-to-end) schrijven. Zo wordt bij een project gewerkt met één set die bij het hele team bekend is, wat discussies over tests gemakkelijker maakt en bijvoorbeeld zorgt dat een tester ook weet wat de achterliggende data is en wat hij aan output kan verwachten op de testomgeving.
Voordelen van automatisch testen
In mijn ogen heeft onze manier van werken een aantal belangrijke voordelen voor developers:
- je ervaart meer ownership bij wat je ontwikkelt en hebt veel meer vrijheid om je eigen ding te doen;
- je werkt niet door elkaar heen, want front-end en back-end zijn beide verantwoordelijk voor hun eigen tests;
- de pipelines werken heel fijn. Als een pipeline faalt, kun je de fout herstellen en daarna pas de merge doorvoeren. Hierdoor breek je niet onbedoeld het werk van anderen, wat natuurlijk best vervelend kan zijn voor de samenwerking en doorlooptijd;
- en je wordt gestimuleerd om waterdichte code te schrijven en dat is heel leerzaam. Je kunt zo écht groeien als developer.
Een voorbeeld CI pipeline die aftrapt bij iedere code wijziging: