Deel 5 - De vier manieren om scripts te bouwen

In de vorige aflevering hebben we gezien hoe handig de testpiramide is bij het kiezen voor automatiseren op GUI, API of unit niveau. In de tweede aflevering had ik al uitgelegd hoe de tools ‘praten’ (tussen aanhalingstekens) met het te testen systeem.

We zijn nu klaar voor de volgende stap: het daadwerkelijke bouwen van geautomatiseerde testen. Meestal komt dat neer op het maken van testscripts en daar zijn grofweg vier manieren voor.

Maar voordat ik je die vier manieren uit de doeken ga doen moet ik je eerst vergiffenis vragen. Het spijt me echt heel erg en ik zal het nooit meer doen. Ik heb je namelijk vier afleveringen lang naar niet-professionele audio laten luisteren. Opgenomen met zo’n ronde speakerphone, met m’n iPhone en zelfs met de ingebouwde microfoon van mijn laptop. Ik dacht dat het er prima mee door kon, maar mijn collega Farshad Kabiri hielp me uit de droom. Ik gebruik nu een semi-professionele Samson GO MIC en als het goed is hoor je dat. Geniet ervan!

Farshad heeft ook een mooier plaatje en het intro en slotmuziekje geregeld en da’s toch leuker dan die metronoomtikken.  Super bedankt Farshad!

Verder hou ik de vorm nog even simpel. Je hoort mijn stem en that’s it. Daar kies ik dus bewust voor. Ik wil eerst een basis leggen met een goed stuk kennisoverdracht. Geen geleuter maar gelouterde kwaliteitscontent. Getoetst, getest, gereviewed en geredigeerd. Gezien het gestaag groeiende aantal luisteraars heb ik het idee dat dat wordt gewaardeerd. Maar de live interviews, gesprekken en groepsruzies gaan echt nog wel een keer komen, maak je geen zorgen.

En nu terug naar het thema: de vier manieren om geautomatiseerde testscripts te maken:

1.       Opnemen: de capture/playback methode

2.       Componeren: met componenten die zijn opgeslagen in een bibliotheek

3.       Programmeren: de scripts zelf coderen ‘from scratch’

4.       Genereren: scripts genereren uit een model (Model Based Testen)

Dus scripts voor geautomatiseerd testen kun je opnemen, componeren, programmeren en genereren. Elk van deze manieren heeft zijn voor- en nadelen. We gaan ze alle vier verkennen, here we go!

Om te beginnen methode 1:

1. Opnemen, de Capture/Playback of Record/Replay methode

Op deze manier bouw je snel en simpel een geautomatiseerde regressietest op. Het werkt als volgt: voer de beschreven test één keer uit op een machine waarop ook de test tool is geïnstalleerd. Die draait in de opnamestand en legt de handelingen van de tester én de respons van het systeem vast. Dit alles komt in een script, dat met één druk op de knop weer afgespeeld kan worden. In de afspeelstand herhaalt de tool alle acties en controleert of de respons van het systeem gelijk is aan de eerste keer bij opnemen. Vandaar de naam capture/playback of record/replay. Dat lijkt handig, en dat is het ook.

Maar........ voor robuuste en onderhoudbare scripts moet er nog meer gebeuren. Eenmaal opgenomen scripts moet je nog voorzien van besturingslogica, herhalingen en foutafhandeling. De interactie met exotische objecten die door de tool niet zijn herkend moet je wellicht apart programmeren. Verder wil je al snel de scripts parametriseren en de data in afzonderlijke invoerbestanden opslaan.

En, niet te vergeten: de eigenlijke verificaties (de checks) moeten meestal toegevoegd of aangevuld worden. Ik zie beginners vaak tevreden achterover leunen als het script soepel en zonder haperingen loopt. Hij doet het!  Dat zegt wel iets, namelijk dat de basale flow van de applicatie in orde is, maar testen is meer dan dat: er moeten velden, berekeningen, meldingen en uitkomsten geverifieerd worden tegen een vooraf bepaalde uitkomstvoorspelling. Sommige tools bouwen automatisch checks in, andere helemaal niet. Vrijwel altijd moeten de checks in het ‘kale’ script  ingebouwd of aangevuld worden.Hoe dan ook: je moet de opgenomen scripts altijd bewerken en daarvoor is het best handig als je de taal van de scripts beheerst. Dat kan een serieuze programmeertaal zijn, zoals Java, C#, of een iets ‘vriendelijkere' scripttaal als Visual Basic of Python. Aan de andere kant: steeds meer tools schermen je volledig af van de code en werken met een fraaie grafische boomstructuur waarin de teststappen voor een niet-ontwikkelaar prima te volgen en te bewerken zijn. Maar ook dat vergt ‘development skills' in termen van modulair opbouwen, netjes parametriseren en hergebruik.

Bovendien past capture/playback niet in ‘test first' aanpakken en kun je er niets mee zolang het te testen systeem nog niet beschikbaar is. Ook kan het zijn dat de tool bepaalde onderdelen of objecten van het te testen systeem niet herkent en het ‘capturen' voor die objecten mislukt en alsnog moet worden geprogrammeerd.

Al met al zien we dat deze techniek tegenwoordig steeds minder als een serieuze optie wordt gezien voor het opbouwen van een herhaalbare en robuuste geautomatiseerde testset. Het dient hooguit als startpunt.

Tot zover het opnemen en daarna afspelen, oftewel capture/playback van scripts. Laten we nu naar de tweede manier van scripts bouwen kijken:

2. Componeren

Scripts kun je ook opbouwen met componenten of objecten die zijn opgeslagen in een bibliotheek of ‘repository'. Zo'n bibliotheek bouw je vooraf op. Dat kan handmatig, maar ook automatisch, door de tool alle onderliggende objecten van de schermen in kaart te laten brengen. Een populaire tool als Tosca bouwt op die manier zijn repository op: per scherm worden alle elementen waarmee interactie mogelijk is vooraf herkend en als bouwstenen in repository modules opgeslagen. In andere tools wordt hiervoor vaak de term ‘page object files' gebruikt.

De script-bouwer kan vervolgens door die lijst van bouwstenen bladeren of ze op de applicatie-schermen zichtbaar maken. Vervolgens kan hij ze achter elkaar zetten, parametriseren en op die manier zonder al te veel programmering robuuste testscripts bouwen.

Met deze aanpak heb je meer controle en flexibiliteit en bouw je beter onderhoudbare testsets op. Je komt er verder mee dan met capture/playback, maar aanvullend programmeerwerk voor de 10 tot 20% exotische situaties blijft meestal noodzakelijk.

Dan nu de derde manier:

3. Programmeren

De testen worden niet opgenomen maar geschreven, geprogrammeerd door ontwikkelaars of door ervaren test automation engineers. Dat vraagt om programmeerervaring met talen als Java, C#, Visual Basic, VBscript, JavaScript of Python. Vaak is het de taal waaraan de developers gewend zijn en waarin ook het te testen systeem zelf wordt gebouwd.

Het grote voordeel van deze benadering is dat de scripts compacter, strakker en leesbaarder zijn dan automatisch gegenereerde scripts. Dat maakt ze robuuster (minder breekbaar, minder ‘brittle' in developers jargon), tijdens de testuitvoering en vooral in onderhoud. En dat laatste is doorslaggevend voor succesvol geautomatiseerd testen met een gezonde Total Cost of Ownership.

We hebben nu drie manieren gehad: opnemen, componeren en programmeren. En dan nu de vierde en laatste manier:

4.    Modelleren / genereren van testgevallen.

Dat kan uit een model van de applicatie:  Model Based Testing noemen we dat. Of met reverse test engineering: testgevallen voor regressietesten genereren uit de bestaande broncode. En natuurlijk met AI, Artificial Intelligence. Dat staat nog in de kinderschoenen, maar uiteraard wordt en is het mogelijk om met AI technologie testen te genereren.

Vooral van Model Based Testen zie we nu echt concrete toepassingen. Dus daar kijken we nog even wat beter naar. Met veel dank overigens aan mijn collega Rob Kuijt, de geestelijke vader van de COVER aanpak en toolbox voor model based testen. We mogen hem gerust een goeroe op dit gebied noemen en in een latere aflevering ga ik hem vast nog een keer interviewen. En als ik toch namen noem: iemand als Jan Tretmans van de Radboud universiteit doet al jaren wetenschappelijk onderzoek naar en ontwikkelt en valideert de concepten voor Model Based Testen.

Het woord ‘model’ moet je breed zien. In feite is elke min of meer gestructureerde beschrijving of plaatje van een aspect van een systeem een model. Voorbeelden van modellen zijn:

1.     Het Business Proces Diagram: een grafische weergave van een bedrijfsproces. Zo’n diagram toont de interactie van (sub)processen met volgorde, triggers, tijdafhankelijkheid, etc... Een hele populaire modelleringstaal en tekentechniek voor bedrijfsprocessen is BPMN2: Business Proces Model Notation, v2.

2.     De Flow Chart, oftewel stroomdiagram of proces flow diagram: een bekende en relatief simpele visualisatie, waarbij blokjes de stappen voorstellen, diamantjes de beslissingen, en pijltjes de volgorde.

3.     Het toestandsdiagram of State Transition Diagram, STD: geeft de verschillende toestanden waarin een systeem zich kan bevinden en de overgangen tussen die toestanden.

4.     Een Beslismodel oftewel een beslissingstabel met bedrijfsregels, meestal business rules genoemd: bepaalt het gedrag voor een specifiek aandachtsgebied

5.     En een hele concrete: het Briefmodel: een model voor het genereren van brieven, mails of andere teksten. Per alinea of tekstelement is vastgelegd onder welke conditie de alinea in de brief verschijnt en met welke variabelen.

Denk ook aan DFD’s, ERD’s, CRUD-matrices, Use Cases, equivalentieklassen, enzovoort.

Voordat aan genereren van code of van testen wordt begonnen kan het model zelf en de beoogde testdekking worden afgestemd met de betrokkenen. Dat werkt natuurlijk preventief, corrigeert interpretatiefouten en past helemaal in de ‘shift-left' ambities van ontwikkelaars en testers.

Veel modelplaatjes zijn globaal en ‘slechts' geschikt voor interpretatie door een mens. Maar zodra een model consistent volgens vaste notatieregels is vastgelegd, is het ook mogelijk om er automatisch softwarecode of testgevallen uit te genereren. ‘Modeldenken' is dus een mes dat aan meer kanten snijdt.De testgevallen die je genereert kun je handmatig uitvoeren, maar de stap van genereren naar geautomatiseerd uitvoeren van de testscripts ligt uiteraard voor de hand.

En dan de tools: Er zijn tientallen tools op de markt die Model Based Testen ondersteunen. Betaald zoals MBTsuite, MaTeLo, BPM-X en Yest van SmarTesting. Een mooie naam van een franse firma die niets met de Valori SmarTEST aanpak te maken heeft overigens. We hebben ooit overwogen ze te suen, maar uiteindelijk een hartstikke leuk klantevent over Model Based Testing met ze georganiseerd. Maar dat terzijde. Ook open source valt er wat te kiezen: Google maar eens op GraphWalker, fMBT en Diversity.

Tot zover de vier manieren om testscripts te maken: Opnemen (capture/playback dus), Componeren, Programmeren en Genereren uit modellen.

En wat is nou de béste manier?

Hier past natuurlijk maar één antwoord en wel het standaard IT-consultants antwoord...: it depends, het hangt er van af! Maar als je de vier manieren snapt en begrijpt zul je zeker in staat zijn om voor jouw situatie de beste keuze te maken. En vaak zal dat een hybride benadering worden. Want een slimme strategie voor geautomatiseerd testen combineert vaak meerdere methodes.

Twee voorbeelden

- Methode 1+3: je neemt een basisset scripts op met de capture/playback techniek en past de opgenomen code vervolgens aan en programmeert aanvullende testen.

- Methode 4+2: je genereert een basisset scripts uit een gestructureerd model. Met deze gegenereerde elementen componeer je een testset door ze ernaar toe te slepen en daarna te configureren.

Op het punt van toepassen en combineren van technieken kunnen de tools behoorlijk verschillend zijn: elke tool heeft zijn eigen filosofie en (on)mogelijkheden.
Tot slot wil ik nog één keer benadrukken dat er veel consensus bestaat dat geprogrammeerde of gecomponeerde testsets beter zijn dan ‘captured' scripts. Ze zijn efficiënter, robuuster, compacter en daarmee beter onderhoudbaar.