Het automatiseren van testen binnen een continuous integration proces is niet meer weg te denken. Binnen ons DevOps-team zijn we op zoek geweest naar een passende oplossing voor testautomatisering. Een oplossing in de vorm van een tool of framework waar ons volledige DevOps-team mee overweg kan. Ieder teamlid moet namelijk in staat zijn tot het aanpassen en uitbreiden van de testen. Daarnaast willen we de testen voor alle door ons te ontwikkelen interfaces en back-end componenten, binnen een enkel framework, kunnen automatiseren. Om aan deze eis te kunnen voldoen, gingen we op zoek naar een framework dat naast het automatiseren van web browsers, REST, SOAP en Unix, ook met databases overweg kan.
Na een kort onderzoek kwamen we tot de conclusie, niet onverwacht, dat er geen eenduidig antwoord is op onze behoefte. De meeste bestaande frameworks zijn te technisch om als team snel resultaat mee te kunnen boeken of voldeden op het moment van onderzoek niet aan de andere gestelde eisen. Robot Framework trok onze aandacht doordat het een losstaand framework is met keywords waar in principe geen directe programmeerkennis voor nodig is. Bovendien voorziet dit framework, door de vele standaard functionaliteiten en add-ons, in een groot deel van onze behoeften.
In dit artikel zullen we verder ingaan op onze ervaringen, de werking en mogelijkheden die Robot Framework biedt.
Wat is Robot Framework?
Robot Framework is een framework voor testautomatisering. De basisideeën van dit framework zijn bedacht in het afstudeerproject van Pekka Klärk in 2005. Later dat jaar is de eerste versie ontwikkeld bij Nokia Networks. Sinds versie 2.0 in 2008 is Robot Framework open source en bevat het een actieve community. Deze community leeft vooral op Github 1 en er zijn nog zeer actieve discussiegroepen op Google Groups 2.
Van origine is Robot Framework ontwikkeld voor end-to-end acceptatie testen en het borgen van acceptatiecriteria op basis van test-driven development. Het is geschreven in Python en gemakkelijk uitbreidbaar door z’n keyword-driven opzet. Robot Framework onderscheidt zich van andere frameworks/tools doordat het gebruikt kan worden voor het testen van applicaties waarbij een combinatie van verschillende technologieën en interfaces gebruikt worden.
Waarom wij kozen voor Robot Framework?
Binnen ons team hanteren we Scrum en dus wordt software op een iteratieve wijze voortgebracht. In een omgeving waarin agile ontwikkeld wordt, is testautomatisering een onmisbaar hulpmiddel. Het belang van regressietesten neemt toe en het snel en vooral vaak kunnen uitvoeren van deze regressietesten is belangrijk. Het automatiseren van deze testen is dus eigenlijk een no-brainer.
Het eerste project van ons team was de realisatie van een SOAP webservice. Voor het testen van deze webservice kwamen we uit bij SoapUI. Dit werkt perfect, omdat SoapUI voor dit doel ontwikkeld is. Een tweede project zou testen moeten bevatten waarbij een Unix batchproces gestart diende te worden en waarbij UI testen nodig zouden zijn. Dit kregen we geïntegreerd in SoapUI door de geschreven Java code als Jar via een Groovy script in SoapUI aan te roepen. Voor het testen van de UI maakten we gebruik van SeleniumIDE, en ook dit kregen we geïntegreerd in SoapUI door middel van de Selenese runner. Op deze manier hadden we één suite waarin het testen van verschillende technologieën mogelijk werd, zelfs vanuit de Maven build. Maar zoals je wellicht verwacht voelde het geheel aan als ‘niet de bedoeling’ en dus niet solide. Het werd tijd om te kijken naar een beter te onderhouden oplossing. Een belangrijke eis, zo niet de belangrijkste, is dat iedereen binnen ons team met het framework overweg moet kunnen en het gebruik gedragen wordt door de verschillende disciplines binnen het DevOps team. Robot Framework voorziet in deze behoeften. Met verschillende voorbeelden en uitleg willen we jullie hier een beter inzicht in geven. We beginnen met een uitleg over de verschillende testaspecten in combinatie met Robot Framework.
Keyword-driven
Om te beginnen is Robot Framework keyword-driven. Keywords zijn eenvoudige leesbare combinaties van woorden. Hierdoor zijn de geschreven testen gemakkelijk te interpreteren en ben je snel in staat om te begrijpen welke handelingen binnen een test suite worden uitgevoerd. Daarnaast is het mogelijk om keywords op een hoger niveau te definiëren, zodat deze stukken code binnen elke willekeurige test ingezet kunnen worden. Hiermee blijft de code onderhoudbaar en de testen overzichtelijk. In het onderstaande voorbeeld is een keyword opgenomen dat gebruikt wordt in een gedefinieerde Test Case. Zie listing 1.
*** Settings *** Library Selenium2Library Force Tags keyword-driven *** Variables *** ${BROWSER} Firefox ${URL} http://squareroots.jdriven.com ${TITLE} Square Roots- Let the Muppets do the work *** Keywords *** Go To Home Of Square Roots Open Browser ${URL} ${BROWSER} Title Should Be ${TITLE} *** Test Cases *** Verify Page Header Go To Home Of Square Roots Page Should Contain Element xpath=//h2 Square Roots! [Teardown] Close Browser
|
Listing 1: Voorbeeld van een keyword-driven Robot Framework test
Data-driven
Een keyword-driven test kan eenvoudig data-driven gemaakt worden door het gebruik van test templates. Binnen een data-driven test wordt slechts één keyword gebruikt, welke door middel van argumenten van verschillende input of output data wordt voorzien. Listing 2 laat een voorbeeld zien.
… *** Keywords *** Calculate Square Root [Arguments] ${squareroot} ${result} Input Text id=inputField ${squareroot} Click Button id=calcBtn Wait Until Element Is Visible id=outputField Element Text Should Be id=outputField ${result} *** Test Cases *** SQUARE ROOT RESULT Square Root Of 1 Is 1 1 Square Root Of 4 Is 4 2 Square Root Of 9 Is 9 3
|
Listing 2: Voorbeeld van een data-driven Robot Framework test
Behavior-driven development
Robot Framework legt je geen restricties op als het gaat om de stijl waarop je de test cases schrijft. Het is dus mogelijk om je testcase volledig uit “high-level keywords” te laten bestaan, waardoor de test cases voor alle stakeholders leesbaar zijn. Op deze wijze is het mogelijk om alle acceptatiecriteria vooraf vast te (laten) leggen in een dergelijke test.
… *** Keywords *** Home Of Square Roots Is Open Open Browser ${URL} ${BROWSER} Title Should Be Square Roots- Let the Muppets do the work Valid Input Is Inserted Input Text id=inputField 100 The Square Root Is Submitted Click Button id=calcBtn The Result Of The Square Root Should Be Shown Wait Until Element Is Visible id=outputField Element Text Should Be id=outputField 10 *** Test Cases *** Valid Calculation Of Square Root Given Home Of Square Roots Is Open When Valid Input Is Inserted And The Square Root Is Submitted Then The Result Of The Square Root Should Be Shown
|
Listing 3: Voorbeeld van een behavior-driven Robot Framework test
Een veelgebruikte stijl om dit te doen is “Given-When-Then”, waarbij de oorspronkelijke staat wordt uitgedrukt met het een keyword dat begint met het woord “Given”. Acties zijn beschreven met een keyword dat begint met het woord “When” en de verwachtingen met een keyword dat begint met “Then”. Als een stap meerdere acties bevat, kunnen de woorden “And” of “But” gebruikt worden. Deze woorden worden door het framework automatisch gefilterd. In listing 3 is deze schrijfwijze opgenomen.
Embedded arguments
… *** Keywords *** The Square Root Of ${squareroot} Should Be ${result} Input Text id=inputField ${squareroot} Click Button id=calcBtn Wait Until Element Is Visible id=outputField Element Text Should Be id=outputField ${result} *** Test Cases *** Calculate Square Roots (embedded arguments) The Square Root Of 1 Should Be 1 The Square Root Of 4 Should Be 2 The Square Root Of 9 Should Be 3 Calculate Square Roots (template with embedded arguments) [Template] The Square Root Of ${squareroot} Should Be ${result} 1 1 4 2 9 3
|
Listing 4: Voorbeeld van een embedded arguments Robot Framework test
Indien je in de naamgeving van een keyword variabelen opneemt, dan dienen deze variabelen als tijdelijke aanduiding voor argumenten. Deze worden vervangen door de werkelijke argumenten binnen de test cases. Gebruik je embedded arguments in combinatie met een template, dan hoeven alleen de te gebruiken variabelen genoemd te worden. Zie listing 4 voor een voorbeeld.
(P OR J)ython
Robot Framework is geprogrammeerd in Python . Er is dan ook een Python 2 of 3 runtime nodig om Robot Framework te kunnen draaien op deze standaard manier. Via de Python manier zijn ook de meeste externe libraries te vinden en makkelijk te installeren via Python’s package manager PIP. Het draaien via Python is dan ook zeker aan te raden. Maar voor de echte Javanen onder ons is het ook mogelijk om je Robot Framework testen te draaien via een Java implementatie van Python, genaamd Jython. Doordat er een JVM gebruikt wordt is Jython tijdens opstarten langzamer dan bij het gebruik van Python. Een situatie waar Jython vaak gebruikt wordt om Robot Framework testen te kunnen draaien is als de Robot Framework testen via Maven of Gradle gestart dienen te worden, om bijvoorbeeld onderdeel te zijn van het bouwproces 3. De losse Jar distributie wordt via Maven Central gedeeld 5. Afhankelijk van welke versie van Robot Framework je gebruikt is er een minimale versie van Java nodig. Naast Jython of Python zijn er ook implementaties van Robot Framework beschikbaar voor IronPython (.NET) en PyPy.
Continuous Integration
De meest ideale situatie is om je Robot Framework testen automatisch mee te laten draaien in je CI-proces. Indien je bijvoorbeeld Jenkins gebruikt is dit eenvoudig op te zetten met behulp van de Robot Framework Jenkins plugin. Via deze plugin kun je instellen welke testen er moeten worden gedraaid op je build server of je remote machine. De rapportage die automatisch gemaakt wordt door het Robot Framework worden via deze plugin ook zichtbaar in je Jenkins job.
Figuur 1: Test resultaten gegenereerd door de Jenkins plugin
Draai je de testen op je build server en maak je gebruik van Selenium? Kijk dan eens naar Headless testen. Headless testen van je applicatie kan via Robot Framework gemakkelijk door de Selenium driver te laten communiceren via PhantomJs of zelfs beter nog via Xvfb. De Xvfb tool zorgt op je linux machine voor een ghost monitor zodat eigenlijk elk programma ‘headless’ gedraaid kan worden. Het bijvoorbeeld headless opstarten van Firefox voor je Selenium testen is dan binnen handbereik, waardoor je het gebruik van een echte browser kunt nabootsen in plaats van een WebKit based browser. Mocht je de mogelijkheid hebben om browserstack 5 te gebruiken dan is dit uiteraard de beste optie om browseronafhankelijkheid in combinatie met met Robot Framework te kunnen garanderen.
Rapportage
Na het uitvoeren van de test cases maakt Robot Framework diverse rapporten voor je aan. Het gegenereerde html rapport geeft een algeheel beeld van de uitgevoerde testen, met het aantal geslaagde en gefaalde testen en de duur van de test suites en test cases. Robot Framework genereert ook een log html file waarbij de details van elke stap binnen de test te vinden zijn. Deze log file is met name handig bij de analyse van een falende test. Je kunt door middel van een gedetailleerde weergave nagaan op welke stap de test case fout is gelopen. Het xml output bestand bevat een samenvatting van de test in de vorm van een xUnit XML resultaat. Deze kan gebruikt worden als input voor externe tools die om kunnen gaan met xUnit rapporten, zoals Jenkins. Uiteraard krijg je de feedback over geslaagde dan wel gefaalde test cases, bij het draaien van Robot Framework via de command line, direct in je prompt.
Figuur 2: Testresultaten zijn direct zichtbaar als je via de command line draait
Ervaring en advies
Robot Framework is door het brede scala aan beschikbare libraries een veelzijdig framework dat een sterke integratie biedt met je CI-proces. Door de keyword-driven opzet blijven testen goed leesbaar en is het framework toegankelijk voor je gehele DevOps team. Het opnemen van Robot Framework binnen je CI-proces is een must. Het delen van de resultaten van de testen, via bijvoorbeeld een groot scherm op je afdeling, zorgt ervoor dat de testen geen ondergeschoven kindje worden. Op iedere codewijziging volgt direct feedback door de resultaten uit de geautomatiseerde regressietest.
Uiteraard zijn er ook frustraties, in ons geval met name bij het gebruik van de Selenium2library (web testing), waarbij de oorzaak meestal ligt in een onvoldoende stabiele opzet van de test. Het gestructureerd opzetten van een framework voor testautomatisering blijft een uitdaging, ongeacht wat het framework je biedt. Wij raden je aan om vanaf start een goede structuur aan te brengen in de opzet van je test suites en test cases, omdat het anders snel rommelig wordt en je een spaghetti krijgt van keywords. De leercurve van het robuust opzetten van deze structuur is helaas wel vrij steil.
Ben je binnen je team op zoek naar een solide oplossing voor het automatiseren van je acceptatie- en/of integratie testen, dan raden wij Robot Framework zeker aan. Bekijk ons Demo project op http://robot-framework-demo.jdriven.com voor veel voorbeelden en hoe te beginnen. Hier zijn ook diverse do’s en don’ts te vinden die je zeker op weg gaan helpen om je eerste eigen Robot Framework test op te zetten. Acknowledge!