top of page

Zoekresultaten

55 resultaten gevonden met een lege zoekopdracht

  • JMeter en Groovy

    Als je binnen JMeter iets wilt doen wat niet standaard in de tool zit, gebruik je plugins of ga je zelf code schrijven. In het geval dat je zelf code gaat schrijven, wordt aangeraden de groovy functie en JSR223 sampler te gebruiken. Ik wil hieronder graag bespreken welke mogelijkheden deze 2 opties je bieden, maar ook waar ik de beperkingen hiervan zie. Groovy JMeter functie In JMeter heb je de __groovy functie. Je kan hier je eigen code in kwijt, maar je kan ook een functie aanroepen uit een (eigen geschreven) groovy file. Voor de laatste optie moet je property groovy.utilities definiëren met het pad naar de groovy file. Deze property is beschikbaar in jmeter.properties. Na aanpassen van de property is een herstart van JMeter vereist. JMeter bevat in de installatie ook een voorbeeld (zie jmeter.properties van je eigen JMeter installatie). Daarin wordt verwezen naar bin/utility.groovy en daarin staat een factorial functie. Aanroepen van deze functie kan dan via: ${__groovy(factorial(10))} Het grootste nadeel van de JMeter functies, waar __groovy er 1 van is, is dat ze niet overal gebruikt mogen/kunnen worden: https://jmeter.apache.org/usermanual/functions.html#where. Waarvan, voor mij, de belangrijkste het “Script” veld is van de JSR223 sampler. Het gebruik van de groovy functie kan in mijn ogen vooral heel handig zijn bij het definiëren van waardes van variabelen (User Defined Variables of User Parameters). Maar ik denk niet dat het handig is voor uitvoerende functies zoals het openen van bijvoorbeeld een database connectie of een MQ queue connectie omdat er geen goede plek is om deze functies uit te laten voeren (het werkt in ieder geval niet vanuit het Script veld van de JSR223 sampler). JSR223 sampler De JSR223 sampler is de andere aangeraden manier om zelf code te schrijven. Bij het gebruik van de JSR223 sampler kan je op 2 manieren groovy code aanroepen/uitvoeren. Dit zijn: Gebruik van veld “Script file (overrides script) -> File Name” Code schrijven in “Script” veld JSR223 sampler – Script file De eerste optie spreekt voor zich: Je kan verwijzen naar een groovy file die de code bevat die je uit wil voeren. Hierbij kan je ook parameters meegeven. Deze kan je bijvoorbeeld gebruiken om de code wat generieker te maken. Je kan dan bijv. code maken voor het connecten met een MQ queue waarbij de parameter de queue naam bevat. Je kan vanuit de JSR223 sampler geen functies aanroepen binnen die groovy file. Je zou hier wel een work-around voor kunnen bedenken zoals een switch statement die een parameter met functie naam als input gebruikt en op basis daarvan een functie aanroept. Voorbeeld: String function = args[0] switch (function) { case "factorial": factorial(10) break case "someFunction": someFunction() break } def factorial(n) { n == 1 ? 1 : n * factorial(n - 1) } Het grote nadeel van “externe” groovy scripts vind ik dat je het JMeter script moet “verlaten” om de code te bekijken of te bewerken. Dit probleem is opgelost door de code in het Script veld te zetten. Het nadeel hiervan is dan weer dat je (mogelijk) die code op meerdere plekken in je JMeter script gaat krijgen. In het volgende stuk bespreek ik welke manieren ik gevonden heb om daarmee om te gaan. JSR223 sampler – Script veld Mijn voorkeur heeft dus het schrijven van de code in het veld Script van de JSR223 sampler. Wat zijn dan de manieren om te voorkomen dat de code niet op meerdere plekken in het JMeter script terecht komt? Dit heeft vooral te maken met de plaatsing van de sampler en de vulling ervan. Ik heb dit opgesplitst in 2 manieren: Gebruik van Test Fragments Functies definiëren en in props of vars zetten JSR223 sampler – Script veld – Test Fragments Je kan een Test Fragment maken en met behulp van een Controller verschillende JSR223 samplers daar onderbrengen. Vanuit de Thread Groups kan je dan door middel van de Module Controller deze functies aanroepen. Voorbeeld: Deze methode werkt heel fijn. Deze functies kan je echter niet aanroepen met parameters. Ik gaf eerder het voorbeeld bij de JSR223 sampler dat je bijvoorbeeld code kan schrijven voor het openen van een MQ queue connectie en dat je dan de parameters kon gebruiken om bijv. de queue naam mee te geven. Dat werkt nu niet. Ik heb dit opgelost door voor het aanroepen van de functie de waardes van een aantal JMeter vars aan te passen m.b.v. User Defined Variables, User Parameters of JSR223 sampler. Een nadeel van deze methode, los van gemis van gebruik van parameters, is dat je alsnog per functie een aanroep controller (module controller) nodig hebt. Mijn voorkeur is 1 JSR223 sampler waarin je de verschillende functies aanroept die je nodig hebt in een iteratie. Dit komt de leesbaarheid van het script ten goede. Hoe je dit doet, wordt in het volgende stuk beschreven. JSR223 sampler – Script veld – Functies in props of vars Een andere mogelijkheid om de groovy code modulair te maken, is door de referentie naar een functie op te slaan in een prop of var: props.put('factorial', this.&factorial) vars.putObject('factorial', this.&factorial) En verder in het script weer aan te roepen: def factorial = props.get('factorial') factorial(10) of in 1 regel: props.get('factorial')(10) Voor vars gebruik je dan vars.getObject(‘factorial’). Het gebruik van groovy code op deze manier heeft zijn voor- en nadelen. Je hebt meerdere mogelijkheden om dit te doen. Een aantal die ik geprobeerd heb: Functies definiëren in JSR223 Pre-Processors. Funtie reference wordt dan opgeslagen in vars object. Functies definiëren in setUp Thread Group. Functie reference wordt dan opgeslagen in props object. JSR223 sampler – Script veld – Functies in props of vars – Pre-processor Als je gebruik maakt van de JSR223 Pre-Processor kan je deze op verschillende niveaus in het Test Plan plaatsen. Ook op het hoogste niveau. Maar bedenk dan wel dat deze pre-processor uitgevoerd wordt bij elke sampler in het Test Plan dat uitgevoerd wordt. Bij heel veel samplers zal dit dan een overbodige actie zijn en zonde van de beschikbare resources. Het voordeel is dan natuurlijk wel dat je op het hoogste niveau al je functies kan definiëren wat het geheel overzichtelijker maakt. Je kan ook de pre-processor op een lager niveau zetten. Maar als een bepaalde functie door verschillende Thread Groups gebruikt wordt, dan heb je alsnog de code op verschillende plekken staan. Dus als je dan toch de pre-processors gebruikt, zou ik dat op het hoogste niveau doen. JSR223 sampler – Script veld – Functies in props of vars – setUp Thread Group De andere optie die ik gaf, was het gebruik van JSR223 samplers in de setUp Thread Group. Dan heb je een mooie verzamelplaats voor je functies. De referentie naar die functies moeten dan wel opgeslagen worden in een prop. De voordelen hiervan zijn: Alle functies zijn mooi verzameld. (dit geldt ook voor gebruik van pre-processor) De JSR223 sampler wordt niet bij elke sampler in Test Plan uitgevoerd. Je kan de code voor 1 iteratie met aanroep naar verschillende functies in 1 JSR223 sampler kwijt. (dit geldt ook voor gebruik van pre-processor) Het nadeel van deze methode is dat de functies in de setUp Thread Group “gemaakt” worden. De vars.get en vars.getObject in de functies werken niet als de functies vanuit een andere Thread Group worden aangeroepen (wat dus wel het idee is van deze methode). Dat betekent dus dat de functies zo gemaakt moeten worden dat ze alle dynamische parameters moeten ontvangen die ze nodig hebben. Variabelen op Test Plan niveau werken hier natuurlijk wel. Maar de functie zal dan wel altijd de oorspronkelijke waarde gebruiken. Dus mocht de waarde van die var aangepast worden, dan zie je dat niet terug in de functie. vars.put of vars.putObject werken ook niet. Dit is ook meteen een voordeel aangezien het best onoverzichtelijk kan zijn waar de verschillende vars binnen het Test Plan een waarde krijgen of waar deze waarde wordt aangepast. Dus in dat opzicht zijn het “schone” functies die niets doen met de bestaande vars. Conclusie Ik heb een aantal manieren beschreven waarop je zelf geschreven groovy code kan gebruiken binnen JMeter. Ik ben heel benieuwd of er nog andere manieren zijn en ook welke ervaringen jullie hiermee hebben.

  • Work hard, play hard!

    Work hard, play hard! Dat laatste hebben we vrijdag 2 juni letterlijk genomen. We zijn naar een museum geweest, het Nationaal Videogame Museum in het stadshart van Zoetermeer. Voor gamefanaten is dit echt een feestje. We kregen een interessante rondleiding waarbij we van alles te weten kwamen over de ontwikkeling van videogames, vanaf de vroege jaren ’70 tot nu. We zagen de allereerste arcadespellen, de legendarische Commodore 64, verschillende videogameconsoles, handhelds en natuurlijk de moderne interactieve spellen. Na de rondleiding mochten we zelfs onze favoriete oude games spelen, of de voor ons nieuwe Japanse spellen uitproberen. Er was zoveel te spelen, het was moeilijk om een keuze te maken. Kortom, het was een leuke middag waarin we konden genieten van onze (oude) liefde voor videogames. Het Nationaal Videogame Museum is echt een aanrader!

  • Meer efficiency en flexibiliteit in API’s

    Er wordt steeds meer gebruik gemaakt van GraphQL API. Tijdens mijn laatste opdracht heb ik hier dan ook mee gewerkt.. Graag deel ik mijn ervaringen hierover in een aantal blogs. In deze eerste blog wil ik het graag hebben over de uitdagingen met REST API en hoe GraphQL deze oplost. Maar eerst even een korte introductie in REST API. We leven in een wereld waarin alles en iedereen door technologie met elkaar is verbonden. Hoe we dat doen? Met API’s, application programming interfaces. Bij het bouwen van een applicatie wordt vaak voor RESTful webservices gekozen om de applicatie met de buitenwereld te verbinden. REST staat voor REpresentational State Transfer. REST API’S definiëren een set aan functies welk de ontwikkelaars/testers kunnen uitvoeren bij het doen van requests en ontvangen van responses via HTTP Protocol zoals “GET”, “PUT”, “POSTS en “DELETE”. Het gaat hierbij om het representeren van resources zoals foto’s, webpagina’s, profielen, artikelen, videoclips etc. via een client-server model. Bij het intypen van een URL in een browser of het klikken op een webpagina link doe je een request naar de webserver en ontvang je een response vanuit de webserver in de vorm van een resource terug. De webserver geeft dus niet een specifiek database als response terug, maar juist een representatie van de database in een formaat wat leesbaar is voor de gebruiker, bijvoorbeeld een HTML pagina of een XML/JSON bericht. Het klikken, scrollen of swipen op webpagina onderdelen geeft je continu een andere staat van de webpagina aan. De resources worden vervolgens in verschillende formaten vanuit de webserver overgedragen naar je webclient. Een REST API is dus een communicatie protocol tussen front-end en back-end. Ongetwijfeld heb je ook over GraphQL gehoord, een open source data querytaal en runtime omgeving die je in staat stelt om een applicatie met de buitenwereld te verbinden. Is dit de eerste keer dat je van GraphQL hoort? Dan heb ik hier een interessante feit: je hebt het al gebruikt of gebruikt het nog steeds! Facebook heeft in 2012 GraphQL intern ontwikkeld en in 2015 op de markt uitgebracht. Het gebruik maken van Facebook betekent dus automatisch het gebruik van GraphQL en dit is bedacht om een aantal uitdagingen die worden ondervonden bij het gebruik van REST API’s op te lossen. Voornaamste doel is om de data uitwisseling tussen API’s en front-end applicaties eenvoudiger, efficiënter en flexibeler te maken. Uitdaging 1: Multiple Endpoints Web en mobiele applicaties zijn steeds meer data-driven en vereisen grote datasets die gerelateerde resources combineren. Om de volledige data op te halen, ook wel “fetching” genoemd, moet men via een REST API vaak meerdere calls uitsturen om alle nodige data te verzamelen om het uiteindelijk aan de gebruiker te representeren. Als een gebruiker bijvoorbeeld op de website van de Telegraaf een opmerking op een willekeurige artikel pagina met een profielfoto en de naam van de auteur opvraagt, dan wordt bij het opvragen van deze data driemaal een roundtrip naar de server gedaan om uiteindelijk over de volledige data te beschikken. Er wordt dus een call gedaan voor zowel de opmerking op de artikel pagina als voor de profielfoto en de naam van de auteur. Met behulp van GraphQL, waarin QL staat voor “Query Language”, kan men zelf query’s samenstellen en hierin zelf exact duidelijk maken wat diegene van de API nodig heeft. De runtime omgeving vertaalt deze query’s naar functies om data op te halen en eventueel te wijzigen. Waar REST API meerdere endpoints nodig heeft voor het ophalen van data, heeft GraphQL er slechts één nodig. Kortom: met een single endpoint kan GraphQL de exacte data ophalen om deze aan de gebruiker te representeren. Niet meer en niet minder! Op deze manier creëer je efficiëntie in je architectuur. Uitdaging 2: Overfetching & underfetching van data Een ander probleem die veroorzaakt wordt bij het gebruiken van een Rest Service is overfetching en underfetching. Met overfetching wordt bedoeld dat de client data ophaalt welke niet noodzakelijk is. Meer data is meer benodigde tijd om de gevraagde data te parsen en te downloaden, waardoor de performance verslechtert. Uit ervaring weet ik, dat in vele gevallen bij het ophalen van klantgegevens zoals naam, achternaam, geboortedatum, adres, woonplaats vanuit de server vaak ook een profielnaam en profielfoto meegegeven worden. De laatste twee worden niet benut en het fetchen van deze data is daarom niet noodzakelijk – You ain’t gonna need it (YAGNI)! Underfetching is het tegenovergestelde van overfetching en houdt in dat er niet voldoende data is voorzien in de Rest Service. De client dient een additionele call te doen om de gewenste data op te halen vanuit de server. Je kunt dit oplossen door specifieke API endpoint te bouwen op de databehoeften van front-end applicaties. Je creëert dan wel meerdere endpoints, waardoor het managen van API’s in je front-end zeer inefficiënt kan worden. Daarnaast is het onderhouden van deze endpoints arbeidsintensief en worden met de tijd onoverzichtelijk. Uitdaging 3: Geautomatiseerde documentatie Bij een technische omgeving maakt men vaak gebruik van een REST API documentatie – swagger – waarin verschillende endpoints met de bijbehorende versies zijn beschreven en deze ook hierin worden onderhouden indien zich wijzigingen voordoen in de applicatie. Het voordeel van GraphQL API’s is dat deze zijn opgebouwd in types & fields en niet in endpoints. Het kloppende hart van een GraphQL API is het schema. In het schema definieer je welke query’s allemaal tegelijk mogelijk zijn op de API. In het schema worden alle objecten en velden vastgelegd die de gebruiker kan opvragen, eventueel met de benodigde relaties van deze objecten. Daarnaast wordt als ondersteuning een tool, GraphiQL, meegeleverd die naast je GraphQL server draait waarmee het schema van de API in een web interface wordt weergegeven en de gebruiker automatisch suggesties krijgt bij het invoeren van de query. GraphiQL verzorgt voor een volledig geautomatiseerd documentatie van de GraphQL API en maakt deze op een centraal repository beschikbaar voor de verschillende API’s, hetgeen leidt tot front-end ontwikkelaar/tester gebruikersgemak. Conclusie In deze blog heb je vooral over de verschillen tussen GraphQL en REST API gelezen. Ik zou zeggen probeer eens GraphQL uit! Door de parallelle samenwerking tussen front-end engineers en back-end engineers kun je sneller features ontwikkelen. Je hoeft dus niet meer te wachten totdat de back-end engineers ontwikkeld hebben om de front-end applicatie op aan te sluiten. Ik ben van mening dat GraphQL de toekomst is en het ziet ernaar uit dat GraphQL API razendsnel populair wordt en de harten van ontwikkelaars veroverd. GraphQL API dient zeker niet als vervanging van de huidige REST API architectuur gezien te worden, maar juist vooral als alternatief. In mijn volgende blog ga ik verder in op het opzetten van GraphQL server met schema om mutaties uit te voeren. Wil je meer weten over GraphQL, dan kun je de volgende webpagina bezoeken: https://graphql.org/.

  • De Absolute Beginners Guide voor API Testen met rest-assured.io

    Omdat het moeilijk was om een eenvoudige tutorial te vinden voor rest-assured.io, ben ik na eerst zelf uit te vinden hoe het werkt, maar eens begonnen met een tutorial die de absolute basics uitlegt over rest-assured. In deze post laat ik zien hoe we op een zo eenvoudig mogelijke manier een API test kunnen maken met behulp van Java en rest-assured.io. Ik gebruik hiervoor IntelliJ IDEA 2107.1.5 Community, standaard installatie met Maven (komt mee met IntelliJ) en Java SDK 1.8 en werk onder Windows 10. Setup In IntelliJ starten we met een leeg Maven project met standaard instellingen. In het nieuwe project zetten we de nieuwe class files in de src/test/java folder en de dependencies in de pom.xml file. Open je pom.xml file en voeg het volgende toe in de node om met rest-assured te kunnen beginnen: io.rest-assured rest-assured 3.0.6 test org.testng testng 6.8.8 com.google.code.gson gson 2.3.1 Mooi, we zijn voorbereid en kunnen van start. Je nieuwe classes zal je voor nu willen plaatsen onder src/test/java. Voeg een nieuwe class toe onder src/test/java (rechtermuistoets, Add -> new class), dit wordt je testclass (de naam maakt niet uit je kan hem later altijd nog renamen met shift + F6). Voor onze eerste testen gebruiken we een eenvoudige API. Later zal je dingen willen doen met authenticatie en wellicht sessies en cookies, maar laten we simpel beginnen. Een simpele API vind je bijvoorbeeld op https://jsonplaceholder.typicode.com/. Zij zijn ook de makers van de json-server waar we later kennis mee gaan maken. Kijk maar even rond op die site. Je kan bijvoorbeeld naar de URL https://jsonplaceholder.typicode.com/posts (<- probeer maar!) gaan om alle blogposts uit de fake-blog api te halen of https://jsonplaceholder.typicode.com/posts/42 om een enkele blogpost op te halen. Eerste Test In onze eerste test gaan we kijken of we connectie kunnen maken met de API. Voeg de volgende methode aan je test class toe: @Test public void getTheFirstPost() { when() .get("https://jsonplaceholder.typicode.com/posts/1") .then() .statusCode(200); } Je zal wat rode kringels krijgen omdat je de imports mist van de rest-assured libraries, laat IntelliJ dat voor je oplossen met de Alt+Enter shortcut. Run de test en als het goed is slaagt hij. Het is handig om de setup in je constructor opzet zodat je dit maar eenmalig hoeft te doen. In dit geval alleen de basic URL, maar je kan hier ook je authenticatie, ports etc. in kwijt. Zie de rest-assured docs voor meer. Ik heb mijn class jsonPlaceHolderTests genoemd, dus mijn constructor heet ook zo: public class jsonPlaceHolderTests { public jsonPlaceHolderTests() { RestAssured.baseURI = "https://jsonplaceholder.typicode.com"; } } Nu hoef je voortaan niet meer de hele URL op te geven, maar alleen de api branch waar je in geinteresseerd bent, in ons geval: @Test public void getTheFirstPost() { when() .get("posts/1") .then() .statusCode(200) .log().all(); } Vaak zal je een given() method gebruiken voor de when() methode, in dit geval is het niet nodig. Een andere verandering is dat we de respons loggen naar de console. Zo kan je zien wat er terug komt aan headers en body: { "userId": 1, "id": 1, "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto" } Body Check In de volgende test kijken we niet naar de repsons code, maar naar de inhoud. Laten we eens kijken of we een assert kunnen schrijven op de userId: @Test public void postShouldHaveUser() { when() .get("posts/1") .then() .body("userId", equalTo(1)); } De equalTo is onderdeel van de HamCrest Matchers collectie, een volledige omschrijving vind je hier: http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/Matchers.html Zo kunnen we eenvoudig bekijken of de titel niet leeg is met de anything matcher: @Test public void postShouldHaveTitle() { when() .get("posts/1") .then() .body("title", anything()); } Of als we willen kijken of alle blog-posts titel bevatten die niet leeg is: @Test public void allPostsShouldHaveAPopulatedTitle() { when() .get("posts") .then() .body("title", everyItem(anything())) } Hier krijgen we een vrij eenvoudig JSON object terug. Als je een complex object terug krijgt kan je specificeren welk gedeelte je wilt testen met de body en wat je daaruit wilt testen met de matchers. De body is het path naar het object toe zoals je dat ook zou doen met een JavaScript object. Het juiste path te pakken krijgen vergt enige oefening zoals met elke path-traversal tool. Toevoegen en manipuleren van data Natuurlijk willen we niet alleen informatie opvragen, maar ook toevoegen, wijzigen of verwijderen. Voordat we verder gaan met post request, zetten we eerst onze eigen JSON server op. Als je nodejs hebt geinstalleerd, heb je automatisch npm waarmee je makkelijk de json server binnen kan halen met: npm install -g json-server Je start de json-server met de volgende commandline. Dit neemt de default db, je kan uiteraard je eigen db maken: json-server --watch db.json als het goed is zal je nu zien dat je json server op port 3000 van je localhost werkt: We maken een aparte class aan voor tests op deze nieuwe omgeving en een test om te kijken of we een resultaat terug kunnen krijgen: public class jsonServerTests { public jsonServerTests() { RestAssured.baseURI = "http://localhost"; RestAssured.port = 3000; } @Test public void firstPostCanBeRetrieved() { when() .get("posts/1") .then() .statusCode(200) .log().all(); } } als het goed is moet deze test slagen. Nu gaan we een nieuwe blog-post ‘posten’. Het posten kost iets meer werk, want we moeten een content type opgeven en de content zelf. De content geven we mee als een HashMap waarvan de values in dit geval simpele strings zijn, maar die natuurlijk ook Arrays of nieuwe HashMaps kunnen zijn. @Test public void newPostCanBeCreated() { Map jsonAsMap = new HashMap(); jsonAsMap.put("title", "My Favorite Towel"); jsonAsMap.put("author", "Arthur Dent"); given() .contentType(JSON) .body(jsonAsMap) .when() .post("/posts") .then() .statusCode(201) .log().all(); } Let op dat je een statuscode 201 terugkrijgt en niet 200. Als je terugkijkt in de db.json file waar json-server in draait, zie je dit object als het goed is weer terug (dit zie je ook terug in de testlog omdat we nog steeds .log().all() gebruiken): { "author": "Arthur Dent", "title": "My Favorite Towel", "id": 2 } Kunnen we een item ook deleten? In onze test gaan we eerst een item aanmaken die we meteen weer verwijderen. Tijdens het aanmaken willen we de id terugkrijgen en wellicht ook de andere properties van de post. Dat kunnen we doen door in de then fase de response te extracten: Response response = given() .contentType(JSON) .body(jsonAsMap) .when() .post("/posts") .then() .extract().response(); De response kunnen we als string uitlezen met behulp van asString(), maar dan moeten we met string manipulaties de Id eruit vogelen. Het zou handiger zijn als we het gelijk om konden zetten in een object en laat dat nou net mogelijk zijn. Als eerste maken we een eenvoudige POJO: public class SitePost { private int id; private String title; private String author; public void setAuthor(String author) { this.author = author; } public void setTitle(String title) { this.title = title; } public void setId(int id) { this.id = id; } public int getId() { return id; } public String getTitle() { return title; } public String getAuthor() { return author; } } En nu moeten we de response omzetten naar dit een SitePost object. Dat gaat verbazingwekkend eenvoudig: SitePost sitePost = response.as(SitePost.class); Het deleten gaat op Id en je krijgt weer een 200 als response code: when() .delete("/posts/{0}", sitePost.getId()) .then() .statusCode(200); De hele test ziet er dus als volgt uit: @Test public void oldPostsCanBeCreatedDeleted() { Map jsonAsMap = new HashMap(); jsonAsMap.put("title", "To Be Deleted"); jsonAsMap.put("author", "Flut Schrijver"); // setup a deletable post Response response = given() .contentType(JSON) .body(jsonAsMap) .when() .post("/posts") .then() .extract().response(); SitePost sitePost = response.as(SitePost.class); // delete it when() .delete("/posts/{0}", sitePost.getId()) .then() .statusCode(200); } Conclusie Hoewel er veel libraries zijn die je kan gebruiken voor rest api calls, is rest-assured.io juist specifiek gericht op testen. Het werkt via de given-when-then triple-A aanpak wat je afdwingt om je testen structureel op te pakken. Het is redelijk eenvoudig om snel een test op te zetten, als zal je bij een wat complexere configuratie ook wat meer moeten configureren met rest-assured. Het doorlopen van de json paden is soms even puzzelen, maar in combinatie met de HamCrest matchers geeft dit een krachtige toolkit om je checks te doen. Ook hebben we in dit voorbeeld laten zien hoe je een respons om kan zetten in een Java object. Er is nog veel meer mogelijk met deze library en daar ligt eigenlijk het heikele punt: er is niet zo heel veel documentatie beschikbaar. Dat was ook een van de redenen om juist een zo eenvoudig mogelijke tutorial hier neer te zetten. Als je deze toolkit wilt gebruiken moet je dus wel wat tijd investeren om het volledig te doorgronden.

  • Wat is het Bug Filter?

    Een algemeen gedeelde opvatting over het doel van testen binnen software ontwikkeling is “het tegenhouden van bugs en het afdekken van risico’s”. Over hoe dit vervolgens het best valt te organiseren, bestaan er echter vaak veel meningsverschillen. In deze 2 minute snack sta ik graag even stil bij een inzicht dat verhelderend werkt in deze discussie, vooral wanneer het budget van belang is… Altijd dus. Mijn dank hiervoor gaat mede uit naar Katrina Clokie, via wie ik de term ‘Het Bug Filter’ als eerste heb gehoord. De Test Automatiserings Piramide van Cohn/Crispin/Huggins kennen we ondertussen allemaal wel. Maar juist op de plek waar er beslissingen gemaakt worden op budgettair vlak, komt deze piramide nogal abstract over. Een veelgehoorde uitspraak is dan ook, “ja, maar als je de frontend test, dan test je indirect ook de backend toch”? Dit heeft dan vaak als uitkomst dat de, in mijn ogen foute, conclusie luidt: “Alleen (geautomatiseerde) testen op de frontend zou voldoende moeten zijn”. Wij hebben het daarom graag over het Bug Filter. Deze wordt soms gevisualiseerd als een omgekeerde test piramide, maar in dit geval stellen we de Build en Deployment Pipeline als een echte pijplijn voor. Elke code check-in start links, gaat door de pijplijn en komt er rechts als het product uit. Om te controleren of de kwaliteit voldoende is kunnen we zoveel filters plaatsen als we willen. De zogenaamde bugfilters. Ze bestaan in drie soorten: De Filters Als eerste hebben we high-speed filters: Ze zijn snel te plaatsen, ze veroorzaken nauwelijks oponthoud wanneer het product passeert en ze zijn ook nog eens goedkoop. Dan hebben we standaard filters: Ze houden een aantal bugs tegen die niet worden tegengehouden door de high-speed filters, maar ze zijn wat lastiger te plaatsen, ze veroorzaken wat oponthoud in de pijplijn en ze zijn behoorlijk duur. Als laatste hebben we ultra-de-luxe filters. Deze zijn nog veel lastiger te plaatsen, ze zorgen voor veel oponthoud en zoals de naam al verraadt zijn ze ook nog eens schreeuwend duur. Waarom je deze aan zou willen schaffen? Nou, omdat ze bugs tegenhouden die niet worden afgevangen door de andere twee filters. De Case Stel je staat in de plaatselijke Bouw-en-Laat-Los winkel (wij hebben alles voor uw build proces) met een budget van 1000 euro. De filters komen met een respectievelijke prijs van 1, 10 en 100 euro. Wat is dan de beste inkoopstrategie? Het Bug Filter gevisualiseerd op de Build Pipeline Inkoop Strategieën We kunnen 10 ultra-de-luxe filters kopen en daarmee houden we inderdaad 5 bugs tegen. Maar 3 ervan hadden we ook kunnen tegenhouden met een high-speed filter, 1 met een standaard filter en inderdaad, 1 hadden we nooit kunnen tegenhouden zonder een ultra-de-luxe filter. De vraag is: Hoeveel bugs hebben we níet tegen kunnen houden? Een andere strategie is eerlijk verdelen: we verdelen het budget (350/350/300) over de verschillende filters voor respectievelijk 350, 35 en 3 filters. Hiermee houden we 87 tegen met het high-speed filter, 6 met het standaard filter en 1 met het ultra-de-luxe filter. Een veel betere score! Of een voortschrijdend inzicht benadering: We kopen net zoveel high-speed filters in totdat we zien dat extra filters niet meer zoveel zin meer hebben. Vervolgens doen we dat met de standaard filters en daarna met de ultra-de-luxe filters. Dit past ook beter bij een Agile aanpak; het maken van geautomatiseerde testen doe je tijden het ontwikkelproces, niet achteraf. Filters en Testen De drie filters staan hier natuurlijk voor unit testen, systeem-en-integratie testen, en de functionele acceptatie testen. Maar praten over “Bug Filters” in plaats van “test soorten” laat veel duidelijker zien waarom alleen frontend automation vaak geen verstandige keus is. Een gebalanceerde benadering biedt better-bang-for-buck, is sneller te bouwen en geeft tijdens build tijd sneller resultaat. Combineer dat met een verstandige plaatsing in de pijplijn en het juiste moment van plaatsing, en je hebt die snelle feedback loop waar al die Continuous Delivery experts het altijd over hebben.

  • De 'waar begin ik met testautomatisering' handleiding.

    Wij worden regelmatig gevraagd te helpen bij het opzetten of verbeteren van testautomatisering in een Agile omgeving bij een klant. En hoeveel ervaring je ook hebt, wat je opdracht ook precies inhoudt en in welk team je ook terechtkomt, het is altijd even zoeken waar te beginnen. Onderstaand stappenplan ondersteunt hierbij. PerformanceArchitecten organiseert veel kennissessies. Zo houden we bijvoorbeeld elke maand een ‘kennismiddag’, waarbij we ruim de tijd nemen voor discussies, om kennis te delen, in een nieuwe tool te duiken, best practices uit te werken etc. De laatste kennismiddag hebben we onder andere met het testautomatiseringsteam besproken hoe te beginnen met een testautomatiseringsklus in een Agile omgeving. Doe er je voordeel mee! 1. Creëer overzicht. We beginnen met het creëren van overzicht. Zorg dat je duidelijk krijgt hoe je omgeving eruit ziet. Breng hiervoor in kaart wie je stakeholders zijn (organisatie), hoe de architectuur er hoogover uit ziet (de techniek) en wat de meest belangrijke functionaliteit is in het product. Wanneer je dit verzameld hebt, documenteer je dit overzichtelijk en teken je dit in maximaal een paar a-4 tjes (praatplaten). 2. Toets de informatie en manage de verwachtingen De volgende stap is om met je praatplaten op zak, jouw beeld van de organisatie, techniek en functionaliteit te toetsen met de stakeholders (PO, Scrummaster, team en de business). Je zal zien dat zij altijd opbouwende kritiek hebben op jouw beeld van de organisatie. Deze fase is erg belangrijk omdat je a: Heel duidelijk ziet of er miscommunicaties bestaan in de organisatie en b: Wat de verwachtingen zijn richting jou, of deze realistisch zijn en wie je belangrijkste sponsoren en/of bedreigingen zijn. 3. Bepaal het risico Zorg dat je vervolgens goed scherp krijgt wat voor de organisatie en jouw stakeholders de belangrijkste risico’s zijn. Wees hier kritisch op jezelf en je omgeving. Vaak zie je dat in eerste instantie ‘alles kritiek is en alles uitvoerig getest moet worden’. Men is niet snel geneigd om aan te geven wat de minder kritische functionaliteit is, omdat men dan in de veronderstelling is dat het vergeten gaat worden. Bedenk ook nogmaals dat risico = het product van kans en impact (K x I). Soms wordt er uitvoerig gekeken naar zaken met hoge impact terwijl de kans dat het voorkomt minimaal is en vice versa. Mocht je hier niet uitkomen kijk dan eens naar een Product Risico Analyse. 4. Bepaal de benodigde inspanning om het te automatiseren Maak voor jezelf duidelijk wat er al is (tooling, test omgevingen, kennis, etc.) Duik ook eens in de verschillende testen en check of de ontwikkelaars al goede unittesten schrijven, hoe de systeem testen gedaan worden en of er integratietesten zijn. Check hierbij ook of er elders in de organisatie in een soortgelijke omgeving wordt gewerkt (wat hebben ze daar liggen). Om tot een goede, evenwichtige en efficiënte testbasis te komen, is het goed om over ‘het bugfilter‘ en/of over het belang van unittesten te lezen. Kijk vervolgens waar en hoe je de testen in de pipeline kan hangen. 5. Wat is prio één, waar begin ik mee, op basis van punt 2, 3 en 4. Nu is het tijd om te bepalen waar te beginnen. Hiervoor gebruik je het overzicht uit stap 1 en de informatie uit stap 2, 3 en 4. Het is hierbij belangrijk om een objectieve afweging te maken tussen waar willen je stakeholders dat je begint, waar zou je moeten beginnen wanneer je de risico’s in acht neemt en waar je het makkelijkst vooruitgang kan boeken. Wees pro-actief bij deze stap. Het zou weleens nodig kunnen zijn om je overtuigingskracht aan te spreken. 6. Zorg voor commitment van het team Wanneer je aan de slag gaat is het zaak om het team te betrekken. Doe dit door duidelijk zichtbaar te maken waar je mee bezig bent en wat de meerwaarde is voor het team. Zorg hierbij dat je kleine porties werk maakt, zodat je vaak wat op kan leveren. Zorg daarnaast ook dat je kennis deelt met je collega’s. Multi-Disciplinair is niet alleen een buzz word, het gaat jou en het team echt helpen om structureel stappen te zetten. Bedenk hierbij dat de testautomatisering onderdeel moet zijn van het product/project. Zo is het onderhoud eenvoudig, creëer je korte feedbackloops en is de herbruikbaarheid van je testen groot. Conclusie Bovenstaand stappenplan is een goed handvat om in een Agile omgeving aan de slag te gaan met testautomatisering. Een Agile Test Strategie is dan ook meer een werkwijze dan een statisch document wat je opvolgt. Testen is geen doel op zich. We doen het zodat we snel feedback krijgen op en vertrouwen hebben in de kwaliteit van het product! Loop jij hier ook weleens tegenaan, of pak jij het op een heel andere manier aan? We zijn benieuwd naar je reactie!! In de toekomst ook op de hoogte blijven? Volg ons dan nu op LinkedIn.

  • Testen? Begin bij de basis! | Het belang van unittesten

    Inleiding Mijn vrouw en ik zijn op dit moment bezig met het bouwen van een huis. In dit geval niet als bouwvakker of aannemer, maar dan toch wel als opdrachtgever. Spannend vinden we het zeker, leuk ook. Wat heeft dit te maken met unittesten zou je denken. Nou, het volgende… Het huis wordt namelijk gebouwd met betonelementen die onder geconditioneerde omstandigheden gefabriceerd en getest zijn om vervolgens kant-en-klaar op de bouwplaats aan te voeren. Daar worden ze met behulp van speciale verbindingen aan elkaar gekoppeld, die er samen met de fundering voor gaan zorgen dat het een stevig en robuust huis gaat worden. De logische indeling hebben we op tekening staan waar we nog jaren plezier van gaan hebben. Het gaat dus nog mooi worden ook! Het vergelijk met softwareontwikkeling is snel gemaakt. De code vormt samen met de architectuur de basis van de applicatie. Die basis is natuurlijk altijd al belangrijk, maar binnen Agile wordt dit nog meer benadrukt. Door de opkomst van Agile softwareontwikkeling heeft unittesten enorme stappen gemaakt. Unittesten vormen een solide basis voor testautomatisering en representeren het grootste onderdeel van de testpiramide van Mike Cohn. Als test (automation) consultant ben ik van mening dat unittesten voor een lager risicoprofiel zorgen bij aanpassingen van je sourcecode en onbedoelde fouten introduceren, hetgeen de kwaliteit van een applicatie ten goede komt. Als ICT-organisatie bespaar je ook simpelweg tijd en geld! Kwaliteit, tijd- en geldbesparing: wie wil dit nou niet? In deze blog wil ik het hebben over de urgentie van unittesten voor zowel de ICT-organisatie als het ontwikkelteam. De definitie van een unittest die ik voor deze blog hanteer: een geautomatiseerd stuk code dat een onderdeel (unit) van een geschreven software aanroept en valideert of het gedrag van dit onderdeel (unit) doet wat het zou moeten doen. Idealiter test je hiermee een klasse of een methode. Als ontwikkelmethode wordt hierbij vaak Test-Driven Development (TDD) gebruikt, waarbij eerst de testen worden geschreven en vervolgens de implementatie van de code. Let wel op dat de applicatie nog steeds fouten kan bevatten terwijl alle unittesten in orde zijn. Het valt me regelmatig op dat de testcases zich vaak beperken tot integratietesten of zelfs enkel tot (geautomatiseerde) functionele testen en in het ergste geval alleen maar tot manuele testen. Dat laatste is echt vragen om serieuze problemen. Zeker wanneer je als ontwikkelteam dagelijks wil uitrollen zijn unittesten onmisbaar. Ze vormen een integraal onderdeel van de Continous Integration – Continous Deployment (CI/CD) Pijplijn. Hoe komt het dan dat TDD of het altijd schrijven van unittesten nog niet vanzelfsprekend is? Hieronder tref je een aantal persoonlijk ervaren tegenwerpingen: 1 – Het kost te veel tijd om unittesten te schrijven Hoeveel tijd en geld kost het de ICT-organisatie vandaag doordat het continu nodig is om te refactoren, te debuggen en om oplossingen voor nieuw geïntroduceerde bugs te vinden? De grootse toegevoegde waarde is niet alleen het voorkomen van productie bugs, maar grotendeels het verkrijgen van “vertrouwen” in het systeem. Bijvoorbeeld het maken van een wijziging in het systeem kan consequenties met zich meebrengen, omdat de kans bestaat dat een ontwikkelaar andere onderdelen van de code kapot maakt. Daarnaast eindigt de ontwikkelaar met een terughoudend gedrag bij de eerstvolgende wijziging die uitgevoerd zou moeten worden op verzoek van de business. Waarom? Het vertrouwen in de applicatie is minder. Als programmeur wil je dan ook niet snel refactoren zolang je de impact hiervan niet makkelijk op de rest van de applicatie kan inschatten. Juist onder andere hierom geven unittesten je bij het refactoren van de code meer vertrouwen en ondersteuning. Kortom: aan het begin van het project kost het schrijven van unittesten inderdaad wat tijd, maar daartegenover krijg je ook meer kwaliteit in je software voor terug en minder bugs op je (scrum)bord. Na paar maanden geïnvesteerd te hebben in unittesten levert softwareontwikkeling je zelf tijdswinst op. 2 – Het duurt te lang om alle testen uit te voeren In dit geval zou ik adviseren om je testen te refactoren of alleen de meest cruciale testen uit te voeren. Een product risicoanalyse (PRA) kan hierbij helpen waarbij de diepgang van de testen is afgestemd op de risico’s. 3 – Onze legacy code is onmogelijk om te testen Als ik dit hoor dan denk ik vaak aan het verhaal van de kip en het ei. Stop hiermee! Dit heeft niks met TDD te maken, maar de legacy code zelf. Bijt door de zure appel heen en begin zo snel mogelijk met het introduceren van de unittesten in je project. 4 – Mijn werk is het schrijven van code en geen unittesten Vaak hoor ik “excuses” van programmeurs “we hebben geen tijd” of “unittesten hebben geen toegevoegde waarde” in softwareontwikkeling. Het werk van jou en de rest van het team is het leveren van “business value” in de vorm van werkende software. Natuurlijk is het doel van programmeurs om kwalitatieve code te schrijven. Echter, zolang er geen unittesten zijn ben ik van mening dat de code niet voldoet aan kwaliteit. Een softwareapplicatie zonder unittesten is voor mij een huis zonder fundering. Als je een huis bouwt, begin je ook met een gedegen fundering. Daarnaast is de kans aanwezig dat bij het oplossen van een bug nieuwe bugs geïntroduceerd kunnen worden die uit de aandacht van de programmeur en/of tester zijn ontsnapt. Een unittest dient in een dergelijk geval als een preventieve maatregel om deze risico af te dekken en de grip op kwaliteit te vergroten. Dus, wat is de toegevoegde waarde van unittesten? Het zorgt voor een veiligheidsnet – we weten dat de code werkt Reduceert kosten en technisch tekort Unittesten fungeren als regressietesten en vormt de basis voor testautomatisering Creëert betere design patterns Focus op het werk dat echt af moet – Definition of Done Onderhoud – het wordt niet moeilijker om te onderhouden zodra je codebase groter wordt Feedback-loop voor validatie code wijzigingen Documentatie Persoonlijk vind ik unittesten prachtig, omdat deze concrete informatie geven aan programmeurs/technische testers waar een onvolkomenheid zich bevindt, bijvoorbeeld op lijn 366 in je sourcecode. Het idee dat testen van units voor het ontwikkelen van softwareapplicatie de kosten doet afnemen en de veronderstelling dat het zo snel mogelijk oplossen van een bug geld bespaart licht ik graag toe met behulp van de onderstaande grafiek. In grafiek 1 is een groene en rode lijn te zien welke de totale kosten over de ontwikkeltijd van twee softwareapplicaties representeert. Grafiek 1 – De totale kosten bij het wijzigen van code De applicatie met rode lijn “Code zonder unittesten” begint met een lagere uitgave dan de applicatie met groene lijn “Code met unittesten”. Het is niet verrassend dat de applicatie zonder unittesten na verloop van tijd meer geld kost, vanwege refactoren, debuggen, ondersteuning teamleden, bugs oplossen, opnieuw releasen etc. Volgens deze beoordeling met betrekking tot kostenbesparing kunnen ICT-organisaties zelf de break-even punt berekenen waarin het testen van units terugbetalen. Na verloop van tijd kun je zelfs de totale besparingen zien helemaal rechts van de grafiek tussen de rode en groene lijn bij het schrijven van unittesten. Daarnaast brengt het wijzigen van willekeurige functionaliteiten of componenten van een applicatie meer risico’s met zich mee bij “Code zonder unittesten”. In grafiek 2 is de uitvoering te zien van “Code met unittesten” met veel minder risico en meer kwaliteit in je software. Grafiek 2 – De risico’s bij het wijzigen van code Softwareontwikkeling is een teamverantwoordelijkheid. Doordat in teams samengewerkt wordt met verschillende achtergronden is iedereen in dit multidisciplinaire team gedwongen om mee te denken en mee te doen met testen. Organisaties zijn steeds meer waarde gedreven en iedereen in het team werkt mee om waarde te leveren. Deze verbreding leidt tot nieuwe kansen voor testers om eerder betrokken te raken bij nieuwe ontwikkelingen (shift left), die bijvoorbeeld hun teamleden kunnen ondersteunen/coachen bij het testen. Zo heb ik tijdens mijn laatste opdracht programmeurs geholpen bij het aanvullen en reviewen van unittesten. Daarnaast heb ik zelf geautomatiseerde functionele testen geschreven met als resultaat een hoger dekkingspercentage in de software. Conclusie Unittesten zijn onmisbaar en vormen een belangrijke schakel in het Agile software ontwikkelproces. De unittesten zorgen niet alleen voor kwalitatief beter software, maar ook het vertrouwen in het ontwikkelteam groeit en bespaart de ICT-organisatie op lange termijn tijd en dus inspanning en geld. Zijn de bovenstaande stellingen jou ook bekend en vind jij dat het echt anders moet, schroom niet om contact met PerformanceArchitecten op te nemen. Ook als je het niet mee eens bent met de stellingen komen we graag met je in contact. Wij van PerformanceArchitecten geloven namelijk heilig in testautomatisering en hebben een uitgesproken visie op ons vakgebied. Samen inspireren en bouwen aan de toekomst!

  • PerformanceArchitecten @The Next Web conferentie

    Was het een interessante conferentie? Beslist. Heeft TNW PerformanceArchitecten op nieuwe ideeën gebracht? Zeker. Heb jij TNW gemist, maar wil je je wel in vijf minuten op de hoogte laten brengen? Lees dan snel verder! En mocht je er wel zijn geweest.. We zijn benieuwd naar jouw beeld! Wat is de Next Web? Voor hen die TNW niet kennen: The Next Web is best veel. Een website, een bedrijf, een event, etc. Zelf zeggen zij: ‘The Next Web — colloquially named TNW — has been sharing, inventing and advancing tech developments since 2006.’ Vrij vertaald: Een breed podium die technologische (IT)ontwikkelingen versnelt, deelt en de innovatie bevordert. In deze blog bespreken we een aantal inzichten, opgedaan op de tweedaagse TNW conferentie 2018 bij de Westergasfabriek. Wat hebben we daar gehoord Om jouw aandacht niet teveel op de proef te stellen, stippen we in dit blog alleen een aantal highlights aan waaruit blijkt dat nieuwe technologie veel impact gaat hebben op de samenleving in het algemeen en onze werkgebieden, performance en automatisering. Dat doen we in een aantal quotes, met linkjes naar de online presentaties en een toelichting. Neem vooral de tijd een aantal van de ‘talks’ te bekijken. Ze zijn zeker de moeite waard! Alles draait om data: “All problems that you can reduce to a data issue, you can solve with AI” (James Whittaker). Neem hiervoor de uitdaging van de zelfrijdende auto als voorbeeld. Zo snel we, met behulp van sensoren, alle problemen die we tegenkomen op de weg, tot data issues kunnen reduceren, kunnen we het oplossen. De weg is data (maps), tegenliggers zijn data (sensoren/camera’s), verkeersinformatie is data, etc. Alles is data… Er stonden op het terrein een aantal borden met ‘waarschuwingen’. Zo was er één met: “Watch out.. Computers do also love your job”. Dit kwam ook in veel praatjes naar voren. Wanneer jouw baan tot data is te reduceren, pas dan maar op: computers will take over. Neem nou een jurist. Veel van het werk bestaat uit het uitzoeken of er jurisprudentie is, in een vergelijkbare zaak met welke hij of zij bezig is. Met Artificial Intelligence in combinatie met data, heb je een geduchte concurrent buiten de reguliere arbeidsmarkt om. Ook deze vorm van robotisering vraagt een heel nieuwe blik op testen. Leuke uitdaging! Artificial Intelligence: “By 2020, the average person will have more conversations with bots than with their spouses.“ (Gartner). De technologie achter chat-bots wordt snel beter. We zullen dan ook zien dat er snel meer business cases gemaakt kunnen worden om bijvoorbeeld helpdesks te laten ‘bemannen’ door bots. Uit een marktonderzoek kwam al naar voren dat mensen liever geholpen worden door goed getrainde bots dan door medewerkers die vanuit een vaak beperkt script moeten werken.. “in 2019, virtual personalities make the leap from functional assistants to true companions” (David Mattin) Het blijkt dat mensen relaties kunnen aangaan met robots. Bizar is te zien hoe snel de technologie zich daarin ontwikkeld. Hierdoor gaan er zeeën van mogelijkheden ontstaan op toepassingsniveau van robots. Dit gaat ook heel nieuwe vraagstukken opwerpen over hoe dit te testen! Design: “conversation is the new interface” Microsoft, (Purna Virji) Purna had een goed en inhoudelijk verhaal over hoe chatbots goed te ontwerpen. Dit deed ze aan de hand van de 4 C’s (Clarity, Character, Compassion en Correction). Een goed voorbeeld is de doelmatigheid waarmee een karakter kan worden ingezet bij een chatbot. Zo gaf ze (bijna aan het eind) een voorbeeld over hoe een bank voor twee verschillende producten, twee verschillende karakters had ontworpen. Op de helpdesk van een formeel product ‘werkt’ een formele bot en bij een hip, informeel product werd een informele bot ingezet. En de klantwaardering? Veel hoger dan bij een helpdesk ingevuld door mensen.. En dan rijst de vraag: Hoe bouw ik een geautomatiseerde testset om het karakter van een bot te toetsen?? Quantum computing: “Each qubit doubles computing power. Quantum computers grew from 5 to 17 qubits in 2 years!” Heike Riel, IBM Natuurlijk, we zien quantum computers nu nog niet in ons dagelijks leven. Maar hoe lang gaat dat nog duren? En dan vooral: Hoeveel rekenkracht hebben we dan tot onze beschikking? Wanneer quantum computers beschikbaar gaan komen in onze werkzaamheden, dan gaat dat veel impact hebben. Rekenkracht zal de bottleneck niet meer zijn Wat voor mogelijkheden geeft dat? En wat is de impact op performance?! En dit gaat echt geen tien jaar meer duren.. Conclusie Door de technologische ontwikkeling verandert de wereld. En dat gaat snel. Bijna sneller dan we voor mogelijk hielden. Dit kan soms beangstigend overkomen, maar het kan ons ook wel degelijk in het dagelijkse leven helpen: van bijvoorbeeld het wegnemen van saai herhaaldelijk werk tot het langer (op oudere leeftijd) zelfstandig te kunnen wonen. En voor ons vakgebied? Hoog-over vanuit QA en performance engineering geredeneerd is ons vak het afdekken van risico’s. Beschikbaarheid van 99,5% van Internetbankieren is acceptabel: als de app of website niet beschikbaar is, dan zal dat niet direct levensbedreigend zijn. Een zelfrijdende auto die in 99,99% van de gevallen de situatie goed inschat en geen ongeluk veroorzaakt voelt weer veel minder acceptabel: faalkans klein, schade enorm. In de nabije toekomst is er steeds meer technologie die wij minder begrijpen en die meer directe impact heeft op ons dagelijks leven. Hoe gaan we voorkomen dat die nieuwe technologieën falen? Wat worden de nieuwe standaarden? Genoeg uitdagingen die een voortdurende innovatie op ons vakgebied vereisen. En die vooruitgang is precies wat ons drijft. Nieuwsgierig waar wij mee bezig zijn op het gebied van innovatie? Neem gerust contact op!

  • Tips en tricks voor Protractor

    Vanuit PerformanceArchitecten doen we graag aan kennisdeling. Van tool reviews tot aan complete best practices maar ook van een aantal simpele tips en tricks die je kan gebruiken in je dagelijkse werk. Vandaag in die laatste categorie voor gebruikers van Protractor: (Javascript) timing issues en het managen van de volgorde van uitvoeren van actions. Inleiding Je kent het waarschijnlijk wel. Foutmeldingen omdat velden niet gevonden worden of tests die slagen terwijl deze niet zouden moeten slagen omdat de timing van je testscripts niet klopt. De volgende tips helpen om je tests meer stabiel en minder risicovol te maken. ExpectedConditions Voorbeeld: Wanneer een pagina af en toe te laat gerenderd wordt en daardoor bepaalde velden nog niet in beeld zijn dan kan het gebeuren dat je test faalt als je op die velden een actie uitvoert. Een browser.sleep (x_seconden) ertussen is een oplossing maar brengt ook een aantal risico’s met zich mee. De test kan ernstig worden vertraagd wanneer de sleep vaak gebruikt wordt. En wie garandeert dat die x_seconden genoeg is? Een alternatief is de ‘Expected Conditions’ library (protractor API). De library bevat onder andere de ‘elementToBeClickable’ functionaliteit waarin je een element en een maximum aantal tijd tot aan de timeout kunt meegeven. Voorbeeld: const { browser, ExpectedConditions: EC } = require('protractor'); await browser.wait(EC.elementToBeClickable(sharedSelectors.buttonSend), 5000); Er zal gewacht worden tot de ‘buttonSend’ aanwezig is en je er op kunt klikken waarna de test verder loopt. Mocht de ‘buttonSend’ niet binnen de 5 seconden aanwezig zijn, dan zal er een timeout melding worden getoond. Zet de timeout dan ook ruim genoeg? API: https://www.protractortest.org/#/api?view=ProtractorExpectedConditions Async/await In protractor test-scripts (asynchroon) kunnen teststappen door elkaar heen gaan lopen qua volgorde. Een manier om de volgorde te managen is de promise manager dat de webdriver (hetgeen waar Protractor bovenop draait) voorbrengt. Omdat de promise manager niet soepel werkt en langzamerhand verouderd raakt, is de ‘async await’ toepassing een ideaal alternatief. Voorbeeld: const putValueInAmountFieldAndClickSend = async amount => { await browser.wait(EC.elementToBeClickable(sharedSelectors.buttonSend), 5000); await pageBonds.amountNominalInput.clear(); await pageBonds.amountNominalInput.sendKeys(amount); await helper.clickSendButton(); } Wat gebeurd hier? In de functie roepen we de ‘async’ functionaliteit aan. Vervolgens kunnen/moeten we voor elke actie een ‘await’ plaatsen. Tijdens het draaien van het script zal protractor wachten tot de actie geslaagd is en doorstromen naar de volgende actie. Wanneer er meerdere actie’s onder elkaar in de functie voorkomen, dan moet overal een ‘await’ geplaatst worden om geen problemen te veroorzaken. Wanneer niet overal een ‘await’ wordt geplaatst kan protractor de weg kwijtraken maar de testrun wel als ‘geslaagd’ bestempelen terwijl er bepaalde stappen niet zijn uitgevoerd. Denk erom dat bij het toepassen van ‘async await’ de node.js versie groter of gelijk is dan versie 8.0 en de Jasmine versie groter of gelijk dan 2.7. Zet daarnaast de volgende regel in je protractor config file: SELENIUM_PROMISE_MANAGER: false . De ‘async await’ functionaliteit werkt namelijk niet goed wanneer de control flow aanstaat. Ben jij hier ook weleens tegen aan gelopen, of heb jij wellicht een alternatieve oplossing gevonden? Heb je er wat aan gehad? We horen graag je commentaar!

  • Impact tooling op performance: Dynatrace

    In deze blog geef ik kort de resultaten weer van een onderzoekje dat ik bij één van mijn laatste opdrachten heb gedaan naar de impact van het gebruik van de tool Dynatrace op de infrastructuur waar het op draait. Mocht je gebruik maken van tooling als Dynatrace of op een andere manier geïnteresseerd zijn in performance denk ik dat je dit zeker interessant vindt. Mijn onderzoekje focuste op java agents die draaiden op Websphere Application Servers. Ik keek vooral naar de impact op CPU en responstijden. Bij de responstijden heb ik me gefocust op 2 veelvoorkomende transacties. Ik heb testjes gedaan met de volgende settings: Dynatrace uit; Dynatrace aan met default settings; Dynatrace aan zonder Exception Sensor Pack; Dynatrace aan zonder Exception Sensor Pack en Auto Sensors resolution level LOW. NB! De resultaten zoals hieronder besproken, hebben betrekking op de applicaties die ik geraakt heb met mijn testen. Deze resultaten zijn niet zomaar te generaliseren. De eerste ronde testen hadden betrekking op de settings bij de eerste 3 bullets. Hieronder mijn bevindingen: Exception Sensor Pack uitzetten zorgt voor een afname van meer dan 50% van geïnstrumenteerde sensors. Exception Sensor Pack lijkt geen invloed te hebben op de responstijden. CPU usage neemt minimaal af bij disablen Exception Sensor Pack Dynatrace zorgt voor een toename in gemiddelde responstijd van circa 10 ms (we hebben het over responstijden van normaal 100 en 190 ms). CPU usage toename van een specifieke applicatie nam relatief 25% toe met dynatrace aan (35% à 44%). In een tweede ronde testen is samen met een Dynatrace specialist gekeken naar manieren om te zorgen dat de overhead omlaag ging; in ieder geval voor de applicatie waar ik zo’n grote impact had gezien. Hierbij was ook de Dynatrace specialist aangehaakt. Het enige verschil met voorgaande testen was dat de resolution level van de Auto Sensors van MEDIUM op LOW werd gezet. Als we dan kijken naar de verschillen tussen Dynatrace uit en deze settings (Auto Sensors op Low en Exception Sensor Pack uitgeschakeld), dan zien we het volgende: De relatieve toename van CPU usage is met slechts 2% afgenomen (25% à 23%). De gemiddelde responstijden van de 2 transacties die ik in de gaten hield, zijn op een paar milliseconden na gelijk aan de andere Dynatrace metingen. Een volgende stap zou kunnen zijn om nog meer Sensor Packs uit te zetten. Het gevaar bestaat dan wel dat er een kans is dat je dingen gaat missen. Een boodschap van de Dynatrace expert: het gebruik van Dynatrace komt met een trade off. Niet verrassend natuurlijk, maar stel jezelf dus de vraag of die trade off acceptabel is ten opzichte van de voordelen van deze tool in de situatie waarin je hem gebruikt. Zo wordt bijvoorbeeld ook de overhead van applicatie logging geaccepteerd vanwege de voordelen die het biedt. Wat ik al aangaf: de resultaten hierboven hebben betrekking op mijn specifieke situatie. De resultaten kunnen verschillen per applicatie en mogelijk ook afhankelijk zijn van de gebruikte infrastructuur. Ik ben heel benieuwd naar jullie ervaringen met Dynatrace en dan vooral of er ook impact was op performance.

  • Visual Regression Testing - Wat is het en wat heb je eraan?

    Visual Regression Testing, of visuele regressie testen, is een categorie van testen die zich focust op het identificer en van visuele wijzigingen tussen iteraties of versies van een website. Dit kan handmatig door schermen of schermafdrukken te vergelijken, maar het is beter herhaalbaar en sneller te testen door dit automatisch te doen. Het mooiste is om deze testen als een van de latere stappen in de build pipeline te plaatsen zodat het volledig automatisch kan, maar als er vaak verschillen zijn (wat niet per-sé regressie, achteruitgang, hoeft te zijn) leidt dit tot veel vals positieven die toch handmatig verwerkt moeten worden. Je kan er dan ook voor kiezen om deze testen op gezette tijden uit te voeren als onderdeel van de Definition of Done van een work-item. Ook helpt het ontwikkelaars om in controle te blijven als ze wijzigingen in de stylesheets moeten doen waar impact mogelijk is door de gehele applicatie heen. Veel VRT frameworks hebben de mogelijkheid om te “approven”. We hebben dit al eerder gezien bij Approval Testing. Ook met Approval Testing is het mogelijk om schermen met elkaar te vergelijken, maar omdat dit een onderdeel in het grotere geheel van Approval Testing is, zijn de mogelijkheden beperkt. Specifieke VRT frameworks hebben vaak meer mogelijkheden door alleen bepaalde schermregionen te testen waardoor de testset een stuk fijnmaziger wordt. Deze regionen worden vaak bepaald door wat er getoond wordt binnen een onderdeel van de HTML-DOM. Selecties van welk onderdeel dat is, gebeurt bijvoorbeeld via xpath expressies of CSS paden. Bepaalde VRT frameworks kunnen headless draaien, dat betekent: testen zonder dat er een browser geopend hoeft te worden; wat een significante versnelling kan betekenen. Ook kan je vaak aangeven op welk device (in het geval van mobile), welke browser, of op welke schermformaat je wilt testen. Deze testen kunnen deels parallel worden uitgevoerd, wat de totale doorlooptijd van de testen flink verkort. Waarom zou je Visual Regression Testing willen? Door de gehele CI/CD pipeline te automatiseren kunnen we steeds sneller nieuwe features naar productie brengen. Onze unit, integratie en acceptatie testen controleren of we geen ongewenste features hebben geïntroduceerd in de nieuwe code, maar dat is over het algemeen op het gebied van data, gedrag of processen. Maar stel dat er per ongeluk een dansende pony in je applicatie verschijnt, dan is het voor een geautomatiseerd proces heel moeilijk om te detecteren dat de ongewenste visuele wijziging heeft plaatsgevonden terwijl het voor een menselijke gebruiker overduidelijk is dat er een verandering is opgetreden.  VRT kan hiervoor een oplossing bieden.  Dat is echter wel afhankelijk van de website die je wilt testen.  Als het een website betreft met veel dynamische content, zoals een nieuwssite, dan is het de vraag of VRT veel toegevoegde waarde heeft. De dynamische content zal immers uitgesloten moeten worden van de test. Indien de website zeer statisch is zal er waarschijnlijk weinig veranderen en zal de toegevoegde waarde van VRT ook laag zijn. De toegevoegde waarde van VRT zit vooral in het feit dat automatisch gecontroleerd kan worden of bepaalde wijzigingen op de website onbedoelde bij-effecten hebben op de layout van de website. Hoe doe je Visual Regression Testing? Nagenoeg alle VRTs werken volgens de Capture, Test, Approve workflow: Capture: Je definieert als eerste schermen en/of regionen die je op een herhaalbare wijze automatisch kan tonen. Van dit scherm of deze regio maak je een schermafdruk, of capture. Dit is de baseline. Test: Bij een nieuwe iteratie wordt van dezelfde regio een capture gemaakt en tegen de baseline capture aangehouden. Indien er een verschil is zal dit gemeld worden, bijvoorbeeld in een testrapport. Approve: Een menselijke gebruiker kan het rapport doornemen te Approven, (de nieuwe capture wordt de baseline), of een incident aan te maken als er daadwerkelijk regressie is opgetreden. Soorten Visual Regression Testing frameworks Op het web zijn er verschillende VRT frameworks te vinden. De verschillen zitten hem in het platform: as-a-service, betaald of open source; de gebruikte taal (JavaScript, Ruby, .NET, Java); onderliggende capture technieken (Selenium al dan niet met PhantomJS, Chromium) en mogelijkheden. Ook onderscheiden de frameworks zich in ondersteuning, community en mate van ontwikkel activiteit, dus in hoeverre het framework onderhouden wordt. Vooral bij browsertesting is dat laatste belangrijk omdat nieuwe browsers de capture functionaliteit kunnen breken van bestaande tools. Hieronder vind je een incomplete lijst van veel genoemde frameworks die laat zien aan welke keuzes je moet denken. Applitools: Dit framework werkt tweeledig. Capturen moet lokaal gebeuren met behulp van applitools eyes library. Dit kan op een tal van omgevingen: Web, iOS, Androis en tal van test frameworks: Appium, Selenium, Protractor en veel meer. Het vergelijken van captures gebeurt as-a-service. De screenshots worden naar applitools verzonden via de API. Je logt in op de website van applitools en daar kan je via een erg gelikte gebruikers interface de verschillen zien en eventueel een nieuwe baseline instellen. Een aparte management tool is handig voor projecten waar het approven door een andere partij wordt gedaan (business gebruikers of testers) dan degene die het framework heeft ingericht. VisualReview: Werk je met Protractor en vind je de API oplossing handig maar doe je dat liever on premise (op je eigen server), dan kan je terecht bij VisualReview. Het management is wat minder gebruiksvriendelijk en de opties zijn iets minder uitgebreid. De laatste commit op het project is ook al even geleden, wat kan duiden op een verlaten project. WebdriverCSS: een andere tool die in eerste instantie veelbelovend lijkt in zijn mogelijkheden is WebdriverCSS. Het leunt zwaar op zijn grote broer WebdriverIO, dus een goede keus als je dit framework al gebruikt. Helaas is de laatste commit van webdriverCSS ook al van twee jaar geleden. Het gebruikt standaard PhantomJS en kan dus headless capturen. Het blinkt uit in het definiëren van regio’s en het instellen van toleranties. BackstopJS: een NodeJS library die zeer goed te configureren is met regio’s en pre-capture scripts. Gecapturede files worden lokaal opgeslagen en kunnen via een handige web interface vergeleken worden met de baseline. De open source library wordt goed onderhouden en support daardoor de nieuwste technieken zoals headless chrome en puppeteer. Het is echter erg Chrome georiënteerd, dus minder geschikt voor multi browser testen. Screenster: deze service neemt je het meeste werk uit handen. Je geeft via de webinterface de URL, device, browser en resolutie op. Om op de juiste plek binnen de webapplicatie te komen kan je ook een klikpad opnemen. Vanaf wordt er gecaptured en kan er vergeleken worden met een nieuwe iteratie. Op deze manier is het ultra low-code en heel bruikbaar voor teamleden die geen ontwikkelaars zijn. Ook heeft Screenster integratiemogelijkheden om de eerder geconfigureerde testen in een geautomatiseerde build te hangen. Zelf aan de slag? Wil je zelf aan de slag, dan zou ik eens beginnen met BackstopJS. Dit framework heeft voldoende ondersteuning, maar door het open source karakter kan je er ook lekker mee kunnen knutselen zodat je beter kan begrijpen hoe VRTs werken. Open source projecten zijn wat dat betreft vaak beter geschikt om mee te experimenteren. Ook in vergelijking met andere open source VRTs steekt deze er boven uit: De grote gebruikerspopulatie en de actieve ontwikkeling in BackstopJS (gemiddeld wekelijks download van 11.500 en veel pull requests), het gemak waarmee het framework geïnstalleerd en geconfigureerd kan worden, mede door de duidelijke documentatie en het gemak waarmee een baseline gecreëerd kan worden en de testen kunt uitvoeren. Installatie en gebruik Eigenlijk wijst de Github pagina van BackstopJS voor zichzelf. Die is erg volledig en bevat meer voorbeelden dan we hier kunnen omschrijven. Toch hieronder een aantal tips en een snelle plug-and-play instructie. Tip: Zorg ervoor dat de laatste versie van NodeJS is geïnstalleerd (BackstopJS werkt alleen met NodeJS 8.0 en hoger) Open een command prompt (CMD/Git Bash/PowerShell) en navigeer naar de map waar je project staat (of waar een nieuw project moet komen te staan). Voer vervolgens de volgende stappen uit: npm install -g backstopjs backstop init backstop test #Bij deze stap zullen de tests falen omdat er nog geen baseline-screenshots zijn gecreëerd. In de volgende stap worden die wél gedefinieerd. backstop approve #Hiermee worden de screenshots die zijn genomen tijdens bovenstaande stap opgeslagen om als baseline te dienen voor toekomstige tests (m.a.w. de website wordt tijdens een test met deze screenshots getoetst op wijzigingen). Tip: als alternatief voor stap 3 en 4 kan initieel ook het commando ‘backstop reference’ worden gebruikt om – zonder een initiële test – baseline-screenshots aan te maken. Het is mogelijk om meerdere scenario’s te testen en te configureren en deze parallel te laten uitvoeren. Deze scenario’s kunnen gebruikmaken van custom scripts om de website in een bepaalde staat te krijgen: denk hierbij aan het inloggen op een website om een gesloten domein te testen of het invoeren van een rekeningnummer om een bepaald mutatieoverzicht te kunnen testen. Handige commando’s hierbij zijn: backstop reference – maak/update  screenshots die als uitgangssituatie zal worden gebruikt backstop test – vergelijk set van baseline-screenshots met nieuwe set van screenshots backstop approve – sla de resultaten van de laatste test op als nieuwe baseline Conclusie Visual Regression Testing lijkt in eerste instantie erg geschikt om afbeeldingen op een website te controleren. Echter kom je er al gauw achter dat afbeeldingen niet vaak wijzigen en als ze wel vaak wijzigen, (denk aan een nieuws website), je ze niet wilt meenemen in je visuele regressie test. Waar VRTs juist wel geschikt voor zijn is het checken van ongewenste effecten van veranderingen in de stylesheet of pagina structuur.  Welk type framework je voor je VRT kiest hangt af van veel factoren: op welk moment in het build proces doe je deze testen, wie implementeert het, hoe technisch zijn de approvers, op welk platform wil je de applicatie testen etc.  In dit artikel stippen we er vijf aan en laten al zien dat ze onderling best kunnen verschillen. We gaan iets dieper in op BackstopJS, een open source tool met een brede community en veel potentie. Echter beperkt het zich tot voornamelijk de Chrome browser en zal je thuis moeten zijn in NodeJS. Maak je al gebruik van WebdriverIO in je testen, dan kan je kiezen voor WebdriverCSS. In andere gevallen kan je bijvoorbeeld meer geholpen zijn met een service en een makkelijke gebruikersinterface en ben je best bereid daarvoor te betalen. We horen graag welk VRT Framework jij gebruikt of zou willen gebruiken en waarom.

  • GPT-Engineer

    Introductie Tijdens onze maandelijkse kennismiddag hebben we kennisgemaakt met GPT-Engineer, een AI-gebaseerde codegenerator. Met GPT-Engineer kan een complete codebase worden gegenereerd op basis van een beschrijvende tekst in een tekstbestand. Dit wordt verzorgt m.b.v. de artificiële intelligentie van OpenAI ChatGPT. GPT-Engineer is een speciale versie van OpenAI’s GPT-3 die werkt als een software-engineer. Het is in staat om code te schrijven, bestaande code te debuggen en optimaliseren, en dat in verschillende talen. Daarnaast kan het technische vragen beantwoorden en complexe informaticaconcepten uitleggen. In tegenstelling tot ChatGPT, dat een breed scala aan onderwerpen behandelt, is GPT-Engineer specifiek getraind voor software-engineeringtaken. Het heeft toegang tot een uitgebreide dataset van programmeer- en technische inhoud, waardoor het beter in staat is om technische vragen te beantwoorden en code te genereren. Tijdens de generatie van de codebase kan GPT-engineer aanvullende vragen stellen om de beschrijving in de prompt te verduidelijken. Je kunt deze vragen zelf beantwoorden of je kunt de artificiële intelligentie van OpenAI-ChatGPT aannames laten genereren. Het resultaat is een codebase waarvan uit direct gestart kan worden. Voor de visueel ingestelde mensen die nu afhaken vanwege de hoeveelheid tekst, is er ook een video waarin GPT-Engineer wordt uitgelegd. Ook andere video's zijn te vinden op YouTube door te zoeken op "GPT Engineer". In het vervolg van dit artikel staat beschreven wat je kan doen om zelf met GPT-engineer aan de slag te gaan. Let op: GPT-engineer is een betaalde service. Je dient geld te storten op je OpenAI-account om het te kunnen gebruiken. De kosten van GPT-Engineer zijn gebaseerd op de hoeveelheid code die wordt gegenereerd. Voor elke 1000 prompt-tokens wordt er $0,03 in rekening gebracht. Voor elke 1000 completion-tokens wordt er $0,06 in rekening gebracht. Een prompt-token is een teken in de prompt-tekst, inclusief spaties. Een completion-token is een teken in de gegenereerde code. Ter illustratie: na tientallen keren GPT-Engineer te hebben gebruikt is er tot nu toe $2,16 verbruikt. Installatie Allereerst dient het volgende te zijn geïnstalleerd om GPT-Engineer te laten werken: Python versie 3.x Pip Maak een account aan en/of login op de site van OpenAI en selecteer de API. In je account gegevens kun je een API key genereren. 3. Op de GitHub pagina van GPT-Engineer staan de instructies om alles werkend te krijgen voor zowel Linux, Windows als MacOS. GPT-Engineer in actie GPT-Engineer was na diverse pogingen uiteindelijk werkend en werd het voorbeeldproject van de GitHub-repository uitgeprobeerd, waarin het promptbestand de volgende beschrijving had: Hieronder staat een screenshot van GPT-Engineer in actie, waarbij er aanvullende vragen terugkomen om de beschrijving verder te specificeren. Ik heb ervoor gekozen om voor deze vragen aannames te laten genereren door OpenAI. Onderaan in de volgende afbeelding is te zien dat er Python code wordt aangemaakt. Resultaat van het gebruik van GPT-Engineer De resultaten van het voorbeeldproject waren enigzins teleurstellend. De aangemaakte Python-code gebruikte telkens modules die niet compatibel waren met de Python-installatie of probeerde in Windows een dll aan te roepen van een Visual C redist die niet op Windows 11 kon worden geïnstalleerd. Dit kan aan verschillende factoren liggen, zoals de geringe kennis van Python, of dat er een betere creativiteit in het formuleren van de prompt benodigd is. Daarenentegen zullen de mogelijkheden en de kracht van AI alleen maar groter worden en de verwachting is dat binnen zeer korte tijd de resultaten beter kunnen zijn. Ondanks de enigzins teleurstellende resultaten, kunnen we GPT-Engineer niet bij voorbaat afschrijven. We raden aan om op de hoogte te blijven van de nieuwste ontwikkelingen op dit gebied, bijvoorbeeld door af en toe een filmpje te bekijken over GPT-Engineer op YouTube.

PerformanceArchitecten

©PerformanceArchitecten

bottom of page