Redactie: Gerben de la Rambelje
Auteur: Pascal Dufour ● pascal@validate-it.nl
In mijn vorige blog ging het over hoe je tot het maken van de juiste feature komt. In deze blog wil ik het hebben over de blauwdruk van een software delivery pipeline. Tegenwoordig kunnen we een volledige deployment doen in minuten en dan zijn er veel zaken automatisch gecheckt.
Hoe zijn we hier gekomen?
Vroeger bouwden we een versie met de hand op de pc van de developer. Met als nadeel dat we afhankelijk waren van de pc met de instellingen van de developer. Om onder andere dit probleem op te lossen werd er gebruikgemaakt van een buildserver. Zo bouwde men een veel beter beheersbare versie van een applicatie. De softwareontwikkeling stond niet stil en door het toevoegen van unittests (checks zoals ik ze graag noem), hebben we al meer vertrouwen gekregen in de applicatie. Vaak stond hier het testen nog ver van de softwareontwikkeling af. Met de komst van extreme programming (XP) en later Scrum is de software craftsman beweging op gang gekomen. Op de buildserver worden meer en meer functies toegevoegd zoals codeanalyse en de geautomatiseerde checks in de vorm van acceptatietesten. Tegenwoordig deployen we zelfs vanuit de buildserver. We gaan nu zover dat we in minuten van een commit (inchecken van code) naar productie kunnen.
De blauwdruk van een software development pipeline
De essentie van een goede development pipeline is dat er snel goede feedback terugkomt om zo snel mogelijk te kunnen handelen. De software delivery pipeline bestaat vaak uit de volgende stappen:
- Committen / inchecken;
- Compilen (eventueel);
- Static code analyse;
- Unittesten;
- Integratietesten;
- Acceptatietesten;
- Deployment naar een testomgeving;
- Additionele testen op de testomgeving zoals:
- Performancetesten;
- Deployment naar een acceptatieomgeving:
- Gebruikersacceptatietest (manueel);
- Wederom additionele testen zoals Performance-, load- en stresstesten;
- Deployment naar productie;
- Final check op productie.
Waarom een software delivery pipeline?
De essentie van een software development pipeline is continuous feedback en het liefst zo snel mogelijk. De eerste stap na het bouwen is vertrouwen krijgen of de code wel aan de richtlijnen voldoet. Dit gebeurt door middel van statische codeanalyse. Hier meten we bijvoorbeeld de cyclomatic complexity; is de code complex. Als de code complex is, is het aannemelijk dat de kans op fouten groter is. Het betekent in de meeste gevallen ook meer testwerk. Er zijn namelijk meer paden te bewandelen. Een andere analyse kan zijn of de code wel voldoet aan de richtlijnen die zijn gesteld. Staan er bijvoorbeeld nog ‘TODO’ in de code?
Stappen in de Unittesten
Bij de stap unittesten hebben we twee concepten die naast elkaar bestaan. Het eerste concept is dat de unittest feedback geeft aan de ontwikkelaar of de code werkt zoals de ontwikkelaar het verwacht had; klopt het design van mijn functie. Het tweede concept is dat de unittesten het contract weergeeft van twee samen werkende delen. Als je wilt refactoren, dan mag je de code wijzigen zolang de unittesten nog aangeven dat het werkt. Uiteraard komen de vervolgstappen om er zeker van te zijn dat het werkt. Na deze stappen hebben we een component die aan onze richtlijnen voldoet en functioneert zoals de ontwikkelaar het bedacht heeft. De volgende stap is het component opnemen in de keten. Vaak zit de meerwaarde niet in een los component maar in de keten/scenario.
Integratietesten
Het testen van het scenario doen we bij integratietesten. We kijken dan niet alleen naar de integratie van componenten maar ook naar het overall scenario. De focus ligt op kleine flows / korte ketens om de integratie van het component te testen. Dit in tegenstelling tot automatische acceptatietesten. Hierbij proberen we juist zo compleet mogelijk de keten te testen. Hierbij gaat het om de flows van de keten. Bijvoorbeeld het testen van een service die een back-end systeem levert. We hebben het hier over value voor de klant. Bij het integratietesten kijken we verder naar het functioneren van het component in de flow en proberen we de waarde vast te stellen die het oplevert. Een goede practice is om de acceptatietesten samen te definiëren in een refinement of story/requirement workshop. Een veel gebruikte techniek is specification by example.
Wat wordt er nu automatisch gecheckt?
De scenario’s zoals bedacht werken en de code is van voldoende kwaliteit. Het kan zijn dat de automatische acceptatietesten niet volledig op de build server kunnen draaien. De vervolgstap is nu het deployen van de software naar een testomgeving. Alle of een deel van de acceptatietesten kunnen op de testomgeving worden uitgevoerd. Nu we weten dat de scenario’s werken, kunnen we additionele testen uitvoeren, bijvoorbeeld een performancetest. Als de testomgeving niet gelijk is aan de productieomgeving, zou het ondanks het verschil toch een indicatie kunnen geven dat de performance niet verslechterd is. Ook dit gaat weer automatisch. Bijvoorbeeld: de duur van de testen mogen niet meer dan 10% of 50% langer duren ten opzichte van de vorige build/dag.
Na de deployment op de test- of acceptatieomgeving kunnen we zeggen dat het de moeite waard is om onze kostbare tijd te gebruiken om deze versie te testen. Hiervan weten we dat de software in potentie doet wat het moet doen. Zoals een goede tester weet, is er geen garantie dat een build op alle omgevingen werkt. Vaak willen we ook nog een aantal bijzondere testgevallen testen zodat we weten dat de scenario’s ook met de bijzondere gevallen goed werkt. Welk testgeval het beste gebruikt kan worden, is niet te voorspellen. Het gebruiken van heuristics om op testideeën te komen helpt (voor mij in ieder geval).
Er zijn zoveel mogelijkheden, kijk eens naar de lijst ‘Your not done yet‘. Of ga eens exploratory testen met Testing Tours.
In dit artikel wordt niet beschreven hoe de versie wordt gedeployed. Hier zijn verschillende methodes voor en is zeer afhankelijk van de omgeving: is er sprake van eigen hardware, maken we gebruik van cloud oplossingen? Cloud wil zeker niet zeggen dat de deployment op een gevirtualiseerde omgeving in de cloud staat. Als je echt naar de cloud zou willen gaan, dan zijn micro services een prachtig idee. Zie hiervoor een interessante video over microservices:
Wordt er gebruikgemaakt van tools zoals docker om deployment eenvoudiger te maken (en vaak heel veel sneller), dan kunnen we nog meer mogelijkheden testen. Er zijn verder nog veel meer mogelijkheden, zoals een omgeving starten met een van te voren bedachte testset en deze vervolgens meerdere malen te herhalen met verschillende testsets.
Tot slot
Waar vroeger het testen voor veel testers ophield bij de acceptatie van het systeem gaan we nu verder. Hoe de applicatie zich gedraagt in productie weten we door monitoring. De vraag is waarom we deze monitoring niet gebruiken op de acceptatieomgeving om allerlei testen uit te voeren. Hierdoor krijgen we echt DevOps. De monitoring van ops biedt vaak goede inzichten waarmee we het ‘every day live’ gedrag van de applicatie kunnen meten. Laten we deze inzichten meenemen naar het ontwikkelen van nieuwe features.
Wat moet je doen als tester om een applicatie goed te testen? Probeer zo snel mogelijk feedback te geven door middel van unittesten tot aan monitoring van de live applicatie. Als tip wil ik je mee geven, vraag jezelf af of je een test of issue niet eerder had kunnen testen of vinden.