Deel 6 - Toekomstvast automatiseren

In de vorige aflevering hebben we gezien dat je geautomatiseerde testen op vier verschillende manieren kunt opbouwen: opnemen, programmeren, componeren en genereren uit modellen. Zoals zo ongeveer alles wat ik tot nu toe heb gezegd en nog ga zeggen heeft dat een relatie met de onderhoudbaarheid en toekomstvastheid van je geautomatiseerde testen. Maar in deze aflevering focussen we extra op Toekomstvast automatiseren

In de SmarTEST praktijk hanteren we namelijk vijf expliciete principes die bijdragen aan een toekomstvaste en onderhoudbare geautomatiseerde testset. Zodat je investering zich wél terugbetaalt en je er langer dan een half jaar plezier van hebt, met een ‘Total Cost of Ownership’ die ook op termijn niet de pan uitrijst. Die vijf extra principes zijn:

  1. Maak onderscheid tussen ontwikkelaartesten en gebruikerstesten
  2. Werk ook bovenin de testpiramide met professionals die onderhoudbare scripts maken met professionele ‘good software design practices’ zoals modulariteit, herbruikbaarheid, uitbreidbaarheid, minimale koppeling en maximale cohesie
  3. Maak onderscheid tussen testen nieuw (progressie) en testen bestaand (regressie)
  4. ‘Design for testability’
  5. Behandel standaardpakketten niet als softwareontwikkeling

Laten we deze principes een voor een eens beter bekijken. Om te beginnen:

Maak onderscheid tussen ontwikkelaarstesten en gebruikerstesten

Geautomatiseerd testen kan zowel ingezet worden door ontwikkelaars voor hun unit testen als door niet-ontwikkelaars voor hun onafhankelijke gebruikersacceptatietesten. Dit zijn twee wezenlijk verschillende sporen. Ontwikkelaars hebben namelijk een ander perspectief, dekken andere risico’s en hanteren andere tools dan niet-ontwikkelaars.

Ontwikkelaars gebruiken graag tools die goed integreren in hun ontwikkelproces en hun ontwikkelomgeving[1]. Liefst command-line, zonder GUI, zodat ze kunnen worden aangeroepen vanuit de scripts van het geautomatiseerde build framework. Soms zijn deze tools onderdeel van de Microsoft .NET of Java of andere ontwikkelomgeving en even vaak worden ‘losse’ open source tools ingezet, zoals JUnit. Ontwikkelaars meten ook steeds vaker de dekkingsgraad van hun testen in termen van ‘code coverage’: het percentage door de testen geraakte coderegels. Dat kan relatief eenvoudig met tools als SonarQube.

Ontwikkelaars hebben meestal geen behoefte aan ‘one size fits all’ tools, maar zetten meerdere tools in combinatie in, al naar gelang de behoefte en de expertise in het team.

Niet-ontwikkelaars, met minder technische expertise zijn meer gebaat bij gebruiksvriendelijke tools met een fijne GUI. Dit soort tools is geschikt voor functioneel E2E ketentesten in een hybride omgeving met verschillende interfaces: browser, non-browser, bestanden en berichten. Vaak zijn dit betaalde tools van de grotere leveranciers zoals Micro Focus (voorheen HP), IBM en Tricentis. Gezien de kosten voor licenties en training wordt hier vaak gekozen voor breed inzetbare tools. Goedkoper en zeer veelzijdig zijn gebruiksvriendelijke capture/playback front-ends op Selenium. Een voorbeeld daarvan is JOSF, een prima alternatief voor de vroegere Selenium IDE capture/playback schil die ook de vastlegging van requirements in het Gherkin Given-When-Then formaat ondersteunt.

De behoefte van ontwikkelaars zal altijd blijven verschillen van niet-ontwikkelaars. Het verschil kan wel vervagen als ontwikkelaars dichter tegen de gebruikers aan gaan zitten (zie ook het kader BDD in paragraaf 1.3) en als gebruikers vroeger betrokken worden en vroeger gaan testen.

Tot zover het 1e principe: ken het verschil tussen gebruikerstesten en ontwikkelaarstesten. Een logisch vervolg hierop is principe 2:

2. Zet altijd IT professionals in die de ‘good software design practices’ kennen

Een geautomatiseerde testset betekent extra onderhoud, of zelfs ‘een softwareproject erbij’, zelfs als je alleen de bovenkant van de testpiramide automatiseert, met gebruiksvriendelijke en intuïtieve tools. Dat betekent dat je altijd ‘good software design’ competenties nodig hebt. Daarom is maximale samenwerking tussen ontwikkelaars, testers en gebruikers onmisbaar, ook al omdat in agile/scrum het team als geheel verantwoordelijk is voor de kwaliteit

Gespecialiseerde testers (in scrum termen: ‘ontwikkelaars in een testrol’) hebben een hoofdrol in de beweging naar zo vroeg mogelijk testen, ook wel de ‘shift-left’ genoemd. Maar zij doen dat niet alleen en werken nauw samen met ontwikkelaars enerzijds en met de gebruikers en stakeholders anderzijds. De ideale taakverdeling voor geautomatiseerd testen volgt de Slager-Keurmeester-Klant taakverdeling:

1.     De slager, oftewel de ontwikkelaar automatiseert zoveel mogelijk
Op het niveau van unit- en integratietesten, daarbij maximaal en naar eigen inzicht gebruikmakend van (open source) tools die bij de ontwikkelomgeving en applicatie-architectuur passen

2.     De keurmeester, oftewel de onafhankelijk tester automatiseert en beheert de regressietesten
Hiermee wordt de bestaande functionaliteit van de totale keten vanuit E2E gebruikersperspectief gevalideerd en voortdurend aangevuld met nieuwe testen.

3.     De klant, vaak de eindgebruiker, heeft veel inbreng, maar automatiseert niet zelfstandig
Want geautomatiseerd testen vergt altijd ontwikkelcompetenties. Zelfs bij inzet van eindgebruikersvriendelijke tools zijn technici nodig voor 10 tot 20% van de testen. De eindgebruiker participeert uiteraard voluit bij het bepalen van de inhoud van de testen op functioneel en keten niveau, maar wordt afgeschermd van de technische en beheermatige aspecten van de automatisering.

Dat was het 2e principe: je kunt niet zonder IT professionals. Dan nu de derde:

3. Maak onderscheid tussen testen nieuw (progressie) en bestaand (regressie)

In agile teams ligt de focus op ‘working software, ready for deployment' en niet op bijproducten zoals te veel documentatie en testware. Zelfs de term ‘throw away testware' komt wel eens langs. Maar zonder gedocumenteerde en herhaalbare testware is een systeem toch niet compleet? Hoe gaan we daarmee om?

Een belangrijk deel van het antwoord op die vraag is: maak verschil tussen progressietesten en regressietesten. Die twee hebben namelijk een verschillende dynamiek, en zijn qua anders qua documentatie en vastlegging.

De progressietesten voor nieuwe functionaliteit documenteer je beperkt en doe je exploratief en handmatig. Je denkt wel vooraf na en maakt vooraf beknopte missies of ‘test charters’, maar de detaillering ontstaat voor een groot deel exploratief, tijdens testuitvoering. Dit is creatief en handmatig werk en is vrijwel niet te automatiseren. Want de focus is op maximale ‘velocity’ en minimale overhead en documentatie tijdens de sprint.

Daartegenover staan de regressietesten, die vragen wél om documentatie en automatisering. Ná elke sprint worden nieuw gemaakte progressietesten toegevoegd aan de vaste regressietestset. Als er bugs zijn gevonden dan worden er scripts toegevoegd die die bugs met zekerheid zouden ‘vangen’ als ze opnieuw zouden optreden.

Maar, zul je zeggen, “Wat nieuw is, wordt oud, dus automatiseer de progressietesten maar meteen, want dat moet toch een keer gebeuren”. Het gekke is dat dit voor de slager/ontwikkelaar goed werkt (TDD!) maar voor keurmeester/klant testen vaak niet. Het is normaal dat de scripts voor unit- en integratietesten worden meegeleverd met de nieuwe software en onderdeel zijn van je Definition of Done (DoD). Maar op keurmeester niveau werkt dat minder goed, want daar pak je de combinatie Informatie/Processen/Systeem. En daar zit zoveel onvoorspelbaarheid en ‘exploratie’, dat automatiseren pas zin heeft na initiële test en oplevering en (meestal) refactoring. Als je dat eerder doet zul je merken dat je heel veel nawerk hebt aan de opgenomen scripts. Bovendien maak je ook risicogebaseerde keuzes: niet alles hoeft getest te worden en niet elke progressietest krijgt een plaats in de regressietesten.

Deze tweedeling past heel goed bij het concept van IT van twee snelheden, door de goeroes van Gartner ‘bimodale IT’ genoemd: enerzijds de snelle sprinters met de nadruk op progressietesten en anderzijds de langeafstandslopers met regressietesten. Die langeafstandslopers zijn de dedicated testers (keurmeesters) en beheerders die de stabiliteit op langere termijn bewaken.

En natuurlijk geldt ook hier weer:

Werk ‘context driven’, het hangt ervan af, elke situatie is weer anders.

Bovenstaande tweedeling is dus wel vaak van toepassing, maar niet altijd in dezelfde mate. Als ketencomplexiteit en risico’s het toelaten kunnen de progressietesten gecombineerd worden met unit- en integratietesten. Dit past helemaal in een integrale TDD, BDD, CI-aanpak. Er is dan alleen maar ‘samen testen’ van de sprint backlog items, door het hele team.

En dat was 3: het verschil in aanpak tussen regressietesten en progressietesten. Dan nummer 4:

4. ‘Design for testability’

Hou in je software architectuur en het ontwerp vanaf het begin rekening met geautomatiseerd testen. Dit voorkomt problemen als:

  • niet herkennen van exotische objecten.
  • opnieuw genereren van object-ID’s waardoor de tool ze niet meer herkent.
  • moeizame root cause analyse van failures door te veel verwevenheid.
  • niet kunnen verifiëren van tussenresultaten.
  • mainstream tooling slecht inzetbaar door niet toepassen van standaardprotocollen en standaard technologie.
  • interfaces die pas in productie getest kunnen worden. Een goede architectuur houdt hier vooraf rekening mee en ondersteunt simulatie van interfaces met stubs, drivers en virtualisatie.
  • testers die door een gebrek aan ontwerpvaardigheden en architectuurinzicht hun testset onhandig en slecht onderhoudbaar opzetten

Dit vereist een nauwe en vroege samenwerking tussen architecten, analisten, ontwikkelaars en testers, ook in refinement en ontwerpsessies.

Samenvattend: in je software architectuur en ontwerp anticipeer je al op geautomatiseerd testen. En dan de laatste, nummer 5:

 

Behandel standaardpakketten niet als softwareontwikkeling

Dit is een inzicht dat maar al te vaak wordt vergeten door organisaties die van elk team een scrum team maken. Het agile/scrum gedachtegoed is ontwikkeld en verfijnd voor en door softwareontwikkelaars. Maar bij standaardpakketten is er niet of beperkt sprake van eigen ontwikkeling. Er kan een zekere samenwerking zijn met de leverancier, maar die heeft meer klanten en zal niet altijd even snel en ‘agile’ inspelen op jouw behoefte. Je kunt best elementen uit scrum toepassen en dat kan zeker goed werken, maar in principe is scrum niet bedoeld voor deze vorm van samenwerking.

Is dat relevant voor geautomatiseerd testen? Ja, want ten eerste is er in dit type teams geen ‘onderkant van de testpiramide'. Die valt namelijk onder de verantwoordelijkheid van de leverancier. Ten tweede zijn er (dus) geen ontwikkelaars met technische skills die kunnen helpen met lastige scripts. Als je gaat automatiseren dan doe je dat voor de belangrijke business scenario's, met de focus op interfaces, maatwerk en inregeling. En niet zozeer op de standaard functionaliteit van het pakket, want die is al getest en bovendien heb je die functionaliteit tijdens de pakketselectie al geaccepteerd. Opzet en onderhoud van deze regressietestset ligt waarschijnlijk bij de beheerders. Zij kunnen niet terugvallen op ontwikkelaars in het team en zullen dus voorzien moeten worden van extra competenties voor het zelfstandig opbouwen en onderhouden van de testset.