Mijn overstap naar Playwright voor frontend end-to-end testen

Nyef
Nyef
Mijn overstap naar Playwright voor frontend end-to-end testen

In deze blog post ga ik het hebben over mijn overstap van Cucumber/Selenium naar Playwright, voor frontend end-to-end testen van webapplicaties. Als softwareontwikkelaar is het namelijk van belang dat ik alle onderdelen van mijn webapplicaties adequaat test met moderne technologieën.

Waarom frontend testen

Als je enkele van mijn case studies leest, zul je merken dat ik altijd code geautomatiseerd test met verschillende technieken. Iedere onderdeel van een softwareoplossing vereist andere testmethoden en technieken. Zo unittest ik backend code met behulp van JUnit. Voor al het visuele, zoals webapplicaties waar eindgebruikers interactie mee hebben, schrijf ik frontend testen.

Frontend test technieken

Er zijn verschillende manieren waarop je de frontend van je webapplicatie kunt testen. Zo kun je iedere losse component geïsoleerd testen. In mijn geval implementeer ik end-to-end testen voor usecases. Tenminste, als ik aan webapplicaties werk, waar ik in deze blog post vanuit ga.

End-to-end testen zijn testen waarin je de flow van verschillende functionaliteiten langsgaat en controleert of alles verloopt zoals verwacht. Daarbij worden niet alleen succes-scenario's getest, maar ook scenario's waarin het verkeerd gaat. Denk aan een foutief ingevuld formulier — in dat geval verwacht je een foutmelding.

Afgelopen jaren heb ik dit soort testen met Cucumber & Selenium gemaakt.

End-to-end testen met Cucumber

Met Cucumber, een zogenoemde behavior-driven development (BDD) tool, schrijf je de testscenario's in een voor iedereen leesbare taal. Deze taal noemen ze Gherkin, hier zie je zo'n scenario voor TheorieGO:

Gherkin

1Feature: Sign in
2
3  Scenario: Successfully authenticate with username and password
4    Given that I have navigated to the admin portal
5    When I type "admin@example.com" in the field "E-mailadres"
6    And I type "************" in the field "Wachtwoord"
7    And I press the button "Inloggen"
8    Then the "Dashboard - TheorieGO Admin" page should be opened

Je kunt in vrij duidelijke taal lezen wat er in het scenario gebeurt en wordt verwacht. Echter, Gherkin stappen werken niet op magische wijze, maar dien je zelf te implementeren.

In zo'n step definition implementeer je het gedrag van de browser en kun je controleren of klopt wat er gebeurt. Dat laatste doe je door middel van assertions, bijv. met de assertions-library Chai.js.

In de volgende code-snippet zie je een voorbeeld van een step definition. Hierin controleer ik of een bepaalde pagina is geopend op basis van de paginatitel:

Typescript

1Then("the {string} page should be opened",
2    async (expectedTitle: string) => {
3        const pageTitle: string = await driver.getTitle();
4        expect(pageTitle).to.equal(expectedTitle);
5    }
6);

Eén van de voordelen van het gebruik van deze methode, is dat niet-programmeurs zelf scenario's kunnen schrijven in de Gherkin-syntax.

Nadeel Cucumber voor mij

Omdat ik veelal aan relatief kleine projecten werk, als freelancer, levert deze manier van frontend testen mij veel overhead op. In mijn geval is er geen behoefte aan BDD, of niet-programmeurs die test scenario's hoeven te schrijven.

Het overslaan van de Gherkin-scenario's zal mij dus tijd besparen. Daarnaast had ik behoefte aan bepaalde features die Cucumber, ten tijde van het schrijven van deze blog, niet ondersteunt. Deze zal ik later toelichten.

Op basis van verschillende adviezen, de aangeboden features, de community (& support), het feit dat het open-source en gratis is, heb ik gekozen om Playwright in gebruik te nemen.

Eerste indruk Playwright

Met behulp van de Getting Started docs van Playwright, kun je vrij snel aan de slag. Je krijgt in eerste instantie dan een voorbeeldproject die je als basis kunt gebruiken.

In Playwright testscenario's doe je twee dingen: Acties uitvoeren ("perform actions") en het resultaat controleren (" assert the state against expectations").

Een testscenario zoals ik in het vorige Cucumber voorbeeld heb gegeven, ziet er bijvoorbeeld zo uit:

Typescript

1test.describe('Sign in', () => {
2
3    test('Successfully authenticate with username and password',
4        async ({page}) => {
5            await page.goto('http://localhost:3000/login');
6            await expect(page)
7                .toHaveTitle('Inloggen - TheorieGO Admin');
8
9            await page.getByLabel('E-mailadres')
10                .fill('admin@example.com');
11            await page.getByLabel('Wachtwoord')
12                .fill('************');
13            await page.getByRole('button', {name: 'Inloggen'})
14                .click();
15
16            await expect(page)
17                .toHaveTitle('Dashboard - TheorieGO Admin');
18    });
19
20});

Met behulp van allerlei design patterns kunnen scenario's worden geoptimaliseerd. Zoals voor het hergebruiken van (delen van) scenario's of selectors.

In eerste instantie was dit voor mij vrij herkenbaar. Enige verschil ten opzichte van Cucumber was dat ik geen Gherkin stappen hoef te schrijven.

Pluspunten Playwright

Voor de Events Toegangsapp heb ik Playwright als eerst toegepast voor het testen van alle flows van de webapplicatie. Hier volgen een aantal pluspunten die ik had ondervonden.

Expect API

Zoals ik eerder toelichtte, gebruikte ik voorheen Chai.js voor assertions. Met Playwright is dat niet meer nodig, aangezien deze met een ingebouwde assertions API komt.

Voorbeeld:

Typescript

1await expect(page.getByText('Showing 1 to 15 of 100 results'))
2    .toBeVisible();
3await expect(exampleDomElement).toBeVisible();

Auto-wait & auto-retrying

Playwright komt met een zogenoemde auto-wait functionaliteit. Als je een actie wilt uitvoeren met een element, dan wacht Playwright totdat dat mogelijk is, ofwel tot het element actionable is. Hierdoor hoef je géén arbitraire delay te gebruiken.

Als je bijvoorbeeld wil klikken op een element, dan controleert Playwright of de locator bestaat, zichtbaar is, stabiel is (niet animerend), events kan ontvangen en enabled is:

Typescript

1await page.getByRole('button', {name: 'Inloggen'}).click();

Daarnaast heeft de assertion library ook auto-retrying assertions. Dat zijn assertions die automatisch opnieuw worden geprobeerd, totdat eraan wordt voldaan of er een timeout optreedt:

Typescript

1await expect(exampleDomElement).toBeVisible();

Locator API

Het is met Playwright niet nodig om een externe selector-library te gebruiken, zoals Selenium. In plaats daarvan biedt Playwright een hoeveelheid aan ingebouwde locators.

Voorbeeld:

Typescript

1const loginButton: Locator = 
2    page.getByRole('button', {name: 'Inloggen'});

Code generator & inspector

Met de code generator tool, codegen, kun je flows opnemen of elementen inspecteren om zo de juiste selector te genereren.

Playwright codegen inspector met de applicatie op de achtergrond

Trace viewer & HTML report

De Trace Viewer GUI-tool laat je traces van uitgevoerde testen zien. Je kunt per stap in je test flow zien hoe de applicatie eruitzag. Daarnaast kun je uit deze snapshots locators zoeken en inspecteren.

Multi-browser & platform

Eén van de voornaamste selling-points van Playwright is de cross-browser functionaliteit. Je kunt jouw test cases laten draaien op verschillende rendering engines, zoals Chromium, WebKit en/of Firefox.

Via het Playwright configuratie-bestand kun je dit snel instellen.

Playwright cross-browser configuratie

De testen zullen dan met de verschillende engines worden uitgevoerd.

Playwright cross-browser testresultaten

Visual comparisons

Playwright heeft een ingebouwde functionaliteit waarmee je de visuele staat van de pagina kunt vergelijken met een screenshot. Zulke screenshots kunnen gegenereerd of geüpdatet worden met Playwright.

Als de pagina er visueel niet uitziet zoals verwacht, kun je dat in de trace viewer zien.

Playwright visual comparisons

Overstap naar Playwright

Hoewel Cucumber (met Selenium) een geschikte framework is voor frontend end-to-end testen, ga ik in toekomstige projecten overstappen naar Playwright.

Wat voor mij de doorslag heeft gegeven zijn de bovengenoemde pluspunten, zoals de trace viewer en ingebouwde cross-browser functionaliteit. Daarnaast is het een steeds vaker gebruikte tool in de industrie en is er een grote community aanwezig voor support.

Naast de benoemde Playwright features uit deze blog post, zijn er nog véél meer. Hier ga ik komende tijd dus zeker mee experimenteren!

Delen

Ervaren software engineer nodig?

Ik help bedrijven met softwareoplossingen (SaaS, automatiseren en meer) — van backend tot frontend. Neem vrijblijvend contact op om te kijken hoe ik kan bijdragen aan jouw project.

  • Robuuste backend: Java/Kotlin, SQL, Spring Framework
  • Gebruiksvriendelijke front-end: Next.js, React, Typescript, ES6
  • Snelle doorontwikkeling: Continuous integration & deployment, Jenkins
  • Efficiënte samenwerking: Agile, Scrum, Jira, Git, Bitbucket, GitHub
  • Freelance software-ontwikkelaar uit Arnhem