Effortless End-to-End Testing with Microsoft Playwright

We. Make. Tests. πŸ› 

Unit tests Integration tests End-to-End tests (E2E)

What Really Are End-to-End Tests? πŸ€–

We can test…

Example 1: registering for a service Example 2: sign in or out of a service Example 3: add products to basket and checkout the purchase

Behaviour-Driven Development (BDD) 🀝

Feature: Calculator

  Scenario: β€œ+” should add to current total.
    Given the current total is β€œ5”.
    When I enter β€œ7”.
    Then the current total should be β€œ12”.

…specs produce tests.

describe('Calculator', () => {
    it('+ should add to current total', () => {
        initialTotal = 5
        number = 7
        
        click('.plus')
        fill('.input', number)
        click('.run')
        
        newTotal = $('.total').innerText
        expect(newTotal).toBe(initialTotal + number)
    })
})

If it’s so simple, why the lack of tests?

It Doesn’t Have to Hurt! πŸ€•

What happens when tests are…

Unstable? Slow to execute? Difficult to write? Painful to maintain?

You likely don’t run or maintain them. 😭

Different teams produce different tests. βš”οΈ

Tests by team

How Playwright Solves the Issues?

Speed and Stability Matter

Perform multiple actions concurrently – never sleep again.
// wait for inputs to be filled with Promise.all() or Promise.allSettled()
await Promise.all([
    page.fill('[data-test-id=username]', username),
    page.fill('[data-test-id=password]', password),
]);

// Executed last
await page.click('[data-test-id=login]');

Support for Modern Languages

Benefit from all the features of TypeScript Set breakpoints and debug in VS Code Support for Python, C#, and Go languages are in preview

Extend How You See Fit

Use any assertion library (eg. assert, chai, or expect) Use any test runner (for now Jest is recommended) Import 3rd party NPM modules

Easy Maintenance

The earlier login example becomes…

const loginPage = new LoginPage(page);
loginPage.fillCredentials(user)
loginPage.login();

Abstraction Layer (POM)

class LoginPage() {
    constructor(page: Page) {
        this.page = page;
    }

    async fillCredentials(user: User) {
        await this.page.fill('[data-test-id=username]', user.name);
        await this.page.fill('[data-test-id=password]', user.password);
    }

    async login() {
        await this.page.click('[data-test-id=login]');
    }
}

Support for Docker Execution

Simple example πŸ‘‡πŸΌ

FROM mcr.microsoft.com/playwright:bionic

WORKDIR /usr/src/app
COPY package.json yarn.lock ./
RUN yarn --frozen-lockfile
COPY . .

CMD ['yarn', 'test:e2e']

Generate Code by Recording Browser Actions

npx playwright-cli codegen https://futurice.com -o test.js

πŸ‘†πŸΌ The URL should be accessible from the network you’re running the test!

Demo

Let’s record a new test from command-line.

Thank You

for question in questions:
  shoot(question)

Check out more of my presentations at slides.nikoheikkila.fi