Een Testautomatiseringsframework met een developers mindset (deel 2)

Recentelijk verscheen deze blog over en met de video van Aditi Mulay op seleniumconf, Londen 2019. Deze eerste blog ging over de zes building blocks zoals gedefiniëerd door Aditi. De wrapper voor webdriver, testdata management, utilities, tracability, rapporteren en browser management. Nu is het de beurt aan het vervolg van haar presentatie. Het tweede deel van de video van Aditi gaat over de development principes van OOPs. OOPs staat hier voor Object Oriented Programming talen. Wil je de video terugkijken? Kijk onderaan deze blog.

Object Oriented Programming talen

De belangrijkste 4 principes van OOPs zijn:

  1. Inkapseling
  2. Overerving
  3. Abstractie
  4. Polymorfisme

Aditi noemt dit de 4 pilaren van OOP oftewel de ‘fantastic four’ van object georiënteerd programmeren. Deze 4 pilaren maken je framework zo onderhoudbaar mogelijk. Je realiseert dit door je framework simpel te beginnen en ruimte te laten voor meer complexiteit. Want zo zegt Aditi: “maintenance, maintenance, maintenance, that is something that always brings us down”. Je wilt dus een framework neerzetten dat makkelijk te onderhouden is, omdat het anders later voor veel vertraging zorgt.

Inkapseling

Het eerste principe is inkapseling. Dit principe bepaalt, dat je een klasse zo inricht, dat je hem alleen kan gebruiken waarvoor je de klasse hebt bedoeld. Het voorkomt, dat je de data kan manipuleren buiten de klasse om. Dit kan je bewerkstelligen door bepaalde methoden of variabelen ‘private’ te maken. Denk dan aan het gebruik van getters en setters. Je wilt niet dat mensen, die jouw code gebruiken, direct een variabele aanpassen, met een setter kan je bepaalde voorwaarden schetsen. De flexibiliteit verbetert en het is ook goed voor de overdraagbaarheid. Waarom? Een nieuwe tester heeft bepaalde kaders waar hij binnen kan werken en hij/zij gebruikt een klasse waar hij voor bedoeld is.

“Maintenance, maintenance, maintenance that is something that always brings us down”

Overerving

Het tweede principe is overerving. Door een bepaalde gelaagdheid / hiërarchie in je testautomatiserings-framework te implementeren kan je variabelen en methodes overerven van een parent klasse.  Een parent klasse bevat alle elementen die een child klasse ook moet hebben. Je zou kunnen bedenken dat er een parent klasse bestaat met de naam ‘Dier’. Dit zou dan bijvoorbeeld als attributen hebben dat het dier een aantal poten of ogen heeft. Een subklasse gebruikt de methoden en variabelen dan (in dit geval het aantal poten of ogen) wanneer je de parent ‘extend’. Vaak heb je in een framework dat verschillende klassen bepaalde gelijkenissen hebben. Zoals de klasse om Chrome of Firefox aan te sturen. Beiden willen een andere browser aansturen, maar ze moeten wel een eenduidige manier hebben hoe ze een webpagina openen of een click actie doen. Bij het selenium framework werkt het als volgt: je hebt een startpunt, namelijk de WebDriver klasse. Deze wordt gebruikt in de RemoteDriver klasse en die wordt weer gebruikt in de ChromeDriver klasse. Dit principe is erg belangrijk voor de herbruikbaarheid van code en dus ook het voorkomen van duplicate code. Het volgende principe, ‘Abstractie’, heeft hier ook weer mee te maken.

Abstractie

Abstractie is het principe dat je alleen de data toont, die relevant is voor die klasse en alle andere data weghaalt. Dit voorkomt onnodige complexiteit. Een implementatie hiervan is, dat je een interface bouwt voor je klasse, een soort schil. Kijk naar de selenium RemoteDriver klasse. Deze gebruikt de WebDriver interface. In deze ‘schil’ staat alleen aangegeven dat, als je de Webdriver gebruikt, je een voorziening moet treffen voor een get actie (navigeer naar), een close actie (sluit de browser) en een quit actie (sluit de volledige driver af). In de RemoteDriver staat vervolgens de daadwerkelijke implementatie. De ChromeDriver klasse gebruikt de RemoteDriver klasse weer door middel van een extend en kan daardoor op een eenduidige manier de functionaliteit gebruiken. Zowel de driver voor Chrome als die voor Firefox gebruikt dezelfde manier om een pagina te openen. Je zorgt hiermee dat de code, die minder relevant is voor een eindgebruiker, niet aan diegene wordt getoond. Als wij de ChromeDriver willen gebruiken is het niet relevant hoe dat onder water precies werkt.

Polymorfisme

Het laatste principe is polymorfisme. Dit betekent dat een methode in verschillende vormen kan voorkomen. Je kan methoden ‘overriden’ en ‘overloaden’. Elke pagina in jouw applicatie heeft waarschijnlijk een knop om uit te loggen. Je zoekt de knop op met ‘id’ en je klikt erop. Elke klasse die deze methode nu overerft, kan hiervan gebruik maken. Stel nu dat er een pagina is, bijvoorbeeld de ListPage, die niet hetzelfde id gebruikt. Je kan nu de methode logout() overriden. Dit doe je door de methode in je subklasse nog eens te noemen. Hier zet je de tag @override voor om een bepaalde methode als het ware te overrulen. Eigenlijk zal je dan altijd de normale logout methode gebruiken om uit te loggen, tenzij je op de ListPage pagina in je applicatie zit. Naast overriden kan je ook overloaden. Dit is als je in één klasse dezelfde methode meermaals neerzet, alleen dan met verschillende hoeveelheden parameters. Stel je hebt een ‘navigateToPage’ methode. Deze heeft één parameter en je gaat direct naar de pagina die jij opgeeft. Het kan ook zo zijn dat je nog naar een child pagina wilt doorklikken. Je kan nu een tweede navigateToPage methode maken met een extra parameter erbij. De ene methode gaat rechtstreeks naar een pagina: navigateToPage(String pageName), de andere methode klikt daarna direct door op een subpagina: navigateToPage (String pageName, String childPage). Op deze manier hou je je code netjes, overzichtelijk en herbruikbaar. Wanneer een nieuwe tester aan de slag gaat hoeft deze niet alle bijzondere methodes, zoals navigateToPageAndThenChildPage,  te kennen. Het is direct duidelijk wat hij of zij kan verwachten.

Tot slot

Hopelijk heb je de 4 basisprincipes van OOP een beetje begrepen en kan jij binnenkort ook inkapseling, overerving, abstractie en polymorfisme in jouw testautomatiseringsframework verwerken. Wat is het belangrijkste dat deze principes verschaffen? Overzichtelijkheid en herbruikbaarheid. Je wilt het liefst dat iedereen direct met jouw code aan de slag kan.