Dit blog-artikel is de laatste in een serie van drie, waarin Tom Heintzberger en Maarten-Jan je meenemen in een aantal ontwikkelingen op het gebied van softwaretesten. Waartoe hebben deze ontwikkelingen ons geleid en welke kansen en perspectieven zien wij voor de (nabije) toekomst?
In ons grote ICT project releasen we nog altijd meerdere keren per dag. We hebben het proces aardig op orde. Elke wijziging gaat door de pipeline, waarin de nieuwe versie na een geslaagde build op een testomgeving geplaatst wordt, zodat daar de geautomatiseerde regressietesten kunnen worden afgedraaid. We hebben een goede verdeling tussen unit-, systeem- en end-to-end testen en het hele team neemt gezamenlijk verantwoordelijkheid voor de kwaliteit van het product. Echter, na verloop van tijd begint het blokje ‘test’ in de pipeline toch wéér een bron van zorg te worden.
Wat wil het geval? Al onze test cases tezamen kennen inmiddels een doorlooptijd van ruim een uur. Omdat we nog vaker kleine wijzigingen willen opleveren, wordt inmiddels elke change zo snel en klein mogelijk gepusht naar het versiebeheersysteem en elke wijziging triggert een nieuwe build.
Op een regenachtige vrijdagmiddag werden op de valreep voor het weekend de laatste wijzigingen ingecheckt, zodat de marketingcampagne voor ons nieuwe product die avond in het reclameblok voor het 8-uur journaal veilig van start kon gaan. De CI server pakte de wijzigingen netjes op en de verschillende branches kwamen in een queue terecht. Na twee minuten bouwen en unit- en systeemtesten werd de eerste deploy naar een testomgeving gestart, waar de integratietesten gingen plaatsvinden. Een uurtje later waren de testen klaar en bleek er nog een kleine bug in te zitten, waardoor klanten geen bestellingen kunnen doen.
Een paar ontwikkelaars hadden voor de zekerheid alvast Chinees besteld en gingen direct aan de slag om een oplossing voor deze bug te implementeren. Een klein uurtje later was de bug opgelost en de wijziging gecommit. Om 7 uur werd de nieuwe versie van het component in de pipeline gezet.
Helaas was dit niet het enige team dat Chinees had besteld: er waren ook nog andere teams actief. Het werd dus een kwestie van achteraan aansluiten: als 3e in de rij ging het reclameblok van het 8 uur journaal bij lange na niet gehaald worden.
Er zijn een aantal dingen die je zou kunnen doen om je pipeline voor dit soort situaties te versnellen. Een belangrijke wijziging releasen via een “fast lane” zou in dit geval kunnen helpen. Niet elke release is even tijdkritisch ten slotte. Een andere oplossing is om meerdere componentreleases tegelijkertijd door de pipeline te halen: op die manier bouw je geen queue op. Een derde mogelijkheid is om componentreleases die geen productiecode wijzigen, niet (direct) naar productie te brengen (bijvoorbeeld enkel wijzigingen in testcode of documentatie). Dit kan een hoop pipeline ontstoppende releases voorkomen, die toch geen nieuwe features opleveren. Maar zelfs met deze (uitstekende) oplossingen wordt het halen van het juiste reclameblok nog steeds krap. Wat zouden we nog meer kunnen doen?
Als we kijken naar de totale doorlooptijd van een pipeline die bouw-, test-, deploy- en integratietest-activiteiten uitvoert, zien we dat de integratietesten in veel gevallen verantwoordelijk is voor het grootste gedeelte van de doorlooptijd. Precies de reden dat het van belang is om zoveel mogelijk ‘laag in de piramide’ te testen. We ontkomen echter vaak niet aan integratie- en acceptatietesten met langere doorlooptijd. We willen tenslotte wel weten dat alle componenten goed samen blijven werken. De gedachte om na elke wijziging te testen is goed, maar toch zijn er best situaties denkbaar waar we met minder dan de volledige testset ook voldoende dekking hadden kunnen halen. Moeten we altijd alle testen draaien? Is het altijd nodig om de regressietest van component X te draaien, of zouden we die kunnen overslaan als onze wijziging geen enkel raakvlak heeft met dat component? Wanneer regressietesten met de hand worden uitgevoerd vragen we de tester toch ook niet om voor elke wijziging alle testgevallen uit te voeren?
In de beweging rond continuous integration & delivery is snellere feedback één van de voorwaarden om succesvol te zijn. Geautomatiseerd testen zóu die feedback moeten versnellen: elke commit wordt direct gebouwd en getest. Eventuele problemen komen dan meteen aan het licht en kunnen direct opgepakt worden. Dat scheelt context switches voor het team en komt daarmee de productiviteit ten goede.
Idealiter zou je de tests die het meest relevant zijn voor jouw change als eerste uitvoeren. Natuurlijk kunnen er altijd onverwachte effecten optreden, maar met de kennis van de applicatie en de testen zijn we vaak best heel goed in staat een ‘educated guess’ te doen over welke tests het meest relevant zijn. Precies dat deden we als testers natuurlijk altijd al, maar met het sneller en vaker releasen en de steeds omvangrijker wordende set van geautomatiseerde testen is dat in de meeste gevallen niet meer haalbaar.
In een tijd waarin elk nieuwsbericht over testen de term “kunstmatige intelligentie” bevat (of het hypetechnisch beter klinkende “artificial intelligence” of “AI”), lijkt een softwarematige oplossing met zelflerende algoritmes voor de hand te liggen. Een neuraal netwerk weet vast wel chocolade te maken van de bergen met testrundata die onze pipeline tot op heden heeft opgeleverd. Waar we allerlei initiatieven in de testwereld zien die ‘AI’ toch vooral gebruiken om een gebruikersinterface te interpreteren (beeldherkenning) en als een soort geautomatiseerde klikrobot door applicaties heen te gaan, zien wij juist in het geautomatiseerd analyseren van historische data en van daaruit optimaliseren van het proces grote verbeterkansen.
Mensen zijn relatief slecht in het nemen van rationele beslissingen en het snel verwerken van grote hoeveelheden ongestructureerde data; juist daar zou kunstmatige intelligentie ons kunnen ondersteunen. Een algoritme zou kunnen helpen inzicht te verschaffen of zelfs keuzes te maken in het proces. Keuzes die niet nieuw zijn, maar door de recente veranderingen in hoe we testen steeds complexer worden en daarnaast steeds sneller en vaker gemaakt moeten worden.
Onze hoop is dat we in deze blogserie duidelijk gemaakt hebben, dat er veel gedaan kan en moet worden voordat zelflerende algoritmes een echte oplossing bieden. We denken zeker niet dat AI de magische oplossing is voor alles: het is een hulpmiddel dat het verschil kan maken tussen “geïnformeerd en snel releasen” en “als de build groen is, zal het wel goed zijn”.
Als we niet langer voor elke wijziging álle testen uitvoeren, maar alleen die testen die ons in korte tijd relevante informatie geven, kunnen we de volgende stap maken in het versnellen van het ontwikkel- test- en leverproces. Mét gebruik van alles wat de laatste technologische ontwikkelingen ons bieden, zónder al teveel te vertrouwen op oplossingen die te mooi lijken om waar te zijn. Het is veel lastiger een algoritme een creatief proces als softwareontwikkeling of -testen te leren, dan het is om een algoritme in te zetten voor het indexeren en classificeren van gegevens. Verder hebben we geleerd, dat optimalisatie niet alleen vanuit AI moet komen. Als we dan toch in modewoorden verzeild moeten raken, klinkt ‘augmented testing’ een stuk realistischer dan testen met ‘AI’.