Unittest frameworks bij functioneel testen: waarom?
Een goede basis voor een automation framework
Als je automatische tests gaat schrijven in code, in plaats van bijvoorbeeld record-playback, word je al snel geconfronteerd met de term unittest framework. Zo kan het zijn dat een collega tegen je zegt dat je die moet gebruiken. Of misschien zie je dat dit framework in een bestaande set-up wordt gebruikt. Maar waarom eigenlijk? Je bent toch niet aan het unit-testen, maar juist functioneel aan het testen?
Setup van een test framework
Natuurlijk ben je bezig met functioneel testen (hoewel de lijn tussen de verschillende testsoorten in een Agile-team steeds dunner wordt). Maar als je een test framework wilt opzetten, zijn bestaande unittest frameworks een goed uitgangspunt. Unittest frameworks zijn, zoals de naam al doet vermoeden, frameworks opgezet ter ondersteuning van de unittesten. De ‘frameworks’ zijn in die zin een verzameling van codecomponenten, bibliotheken, standaarden en zelfs afspraken die bepaalde doelen ondersteunen. Dat klinkt misschien heel abstract, maar je hebt ze dan ook voor veel verschillende doelen. Naast frameworks voor unittesten, zoals JUnit en TestNG, zijn er ook algemene frameworks zoals ASP.NET, .NET en Cocoa.
Unittest frameworks
Unittest frameworks zijn opgezet om unittesten te organiseren door verschillende ondersteunende onderdelen te bieden. Een van de eerste unittest frameworks was SUnit voor de ontwikkeltaal Smalltalk. Dit was de bron van een hele serie xUnit-frameworks. De eerste letter(s) van de naam van de frameworks uit deze serie geven aan voor welke taal deze is (jUnit is voor JAVA, rUnit is voor R). De xUnit frameworks zijn allemaal opgezet met dezelfde onderdelen en het zijn juist deze onderdelen die de frameworks zeer bruikbaar maken voor functioneel testen. Naast de xUnit-serie frameworks zijn er nog andere unittest frameworks, zodat er altijd wel eentje past in de omgeving waar je testen in schrijft.
Onderdelen van een unittest framework
Per unittest framework verschillen de onderdelen. Hieronder staat een algemeen voorbeeld van de onderdelen in een unittest framework:
- Test runner: een uitvoerbaar programma dat de tests uitvoert met behulp van het framework en de resultaten terugrapporteert.
- Test suites: een verzameling tests die allemaal dezelfde uitgangssituatie hebben en daarbinnen in een willekeurige volgorde worden uitgevoerd.
- Test execution: het uitvoeren van een test met een setup en teardown script. Het setup script zet alle voorwaarden klaar voor de test (bijvoorbeeld: start de browser op en open de website). Het teardown script ruimt alles na de test weer op (bijvoorbeeld: log uit als het kan en sluit de browser af).
- Test result formatter: en onderdeel die de resultaten vanuit de test runner formatteert, vaak in XML. Deze resultaten kunnen daarna geïmporteerd worden in bijvoorbeeld Jenkins.
- Assertions: een assertion is een bewering die waar of niet waar moet zijn om een test te laten slagen. Het framework biedt assertions aan in verschillende variaties die, als ze niet slagen, de test laten falen. Een assertion is over het algemeen opgesteld als: assert dat waar is: het element op locatie X is ‘welkom op onze site’. Als op locatie X die tekst niet staat, dan zal de test daarop falen met vermelding van deze bewering. Het voordeel hiervan is dat als een bewering faalt, alleen de test faalt en niet de hele run.
- Data driven tests: er kan op verschillende manieren een lijst aan parameter sets meegegeven worden, waardoor dezelfde tests meerdere malen met andere parameters kunnen worden uitgevoerd.
- Distributed testing: het uitvoeren van tests op slave machines. Hierdoor kun je tests op een andere computer uitvoeren, zodat de aansturende computer er geen last van heeft, zoals bij de vele browserschermen bij Selenium het geval kan zijn.
- Annotaties:met annotaties kun je per testmethode aangeven wat de bijzonderheden ervan zijn. Zo kan je tests prioriteren, een beschrijving meegeven, linken aan testcases in een bevindingen managementsysteem of aangeven welke story of epic hiermee getest wordt.
Voor sommige van deze onderdelen is het gebruik verplicht, zoals het stukje code dat aangeeft dat een bepaalde klasse of methode een test is. Andere onderdelen, zoals assertions, zijn niet verplicht. Met een unittest framework heb je dus een stapel hulpmiddelen waarmee je je eigen set-up helemaal kunt inrichten.
Unittest frameworks voor functioneel testen
Als je zo de eigenschappen van een framework leest, zie je waarschijnlijk al dat deze functionaliteiten ook bij functioneel testen bruikbaar zijn. We nemen een set-up met Selenium binnen het TestNG-framework als voorbeeld:
- Je kunt je tests in suites uitvoeren, waardoor je tests voor dezelfde onderdelen op een webpagina kunt groeperen. Deze gebruiken dan dezelfde setup/teardown-scripts. Daarnaast bieden test suites ook de mogelijkheid om je tests per onderdeel te groeperen, waardoor gericht (her-)testen makkelijker wordt.
- Je kunt data driven tests gebruiken en eventueel zelfs de data laten halen uit een extern bestand, zodat ook een minder technisch onderlegde tester data kan aanleveren. Denk bijvoorbeeld aan het klikken op een set van links en het controleren van de paginatitel. Met parameter sets kun je één test schrijven (klik op link, assert page title) en dan een set aan parameters maken van iedere link ID en page title.
- Je kunt de verwachte resultaten in je test zetten, waardoor de test vele controles kan uitvoeren en bij het falen van deze controles netjes rapporteert wat er mis is gegaan. Denk bijvoorbeeld aan een controle van de weergegeven tekst na het foutief inloggen of juist het weergeven van de correcte welkomsttekst na correct inloggen.
- Na de testuitvoer krijg je de resultaten in een mooi rapport. Deze rapportages zijn bij de meeste frameworks zo standaard, dat je ze automatisch in bijvoorbeeld Jenkins of Confluence kan laten weergegeven. Er zijn ook tools die het rapport zo maken, dat het ook voor management te gebruiken is.
- Je hebt daarnaast ook geen static main-methode meer nodig om je tests uit te kunnen voeren, door de aanwezigheid van de test runner.
Ik hoop dat je een beeld hebt gekregen van wat een unittest framework is en waarom het voor automatische functionele tests een heel goed hulpmiddel kan zijn. Tot slot wil ik jullie wijzen op de mogelijkheid om zelf aan de slag te gaan met tutorials van Guru99 en ToolsQA die een korte how-to geven van Selenium samen met TestNG.