How to test web pages?

Playwright is a modern alternative to Selenium for remote-controlling a web browser, accessing pages, filling forms and accessing the HTML content. You can use playwright both for testing web pages and scraping or run it in CI in headless mode.

Install it with:

pip install playwright
playwright install

Playwright can remote-control the browsers Chrome, Firefox and Safari. It covers all steps of a web session such as visiting pages, filling forms, and interacting with dynamic page elements. This makes Playwright excellent for end-to-end tests and extensive automations.


from playwright.sync_api import sync_playwright


with sync_playwright() as p:
    browser = p.firefox.launch(headless=False)
    page = browser.new_page()
    page.goto("http://www.academis.eu")
    page.is_visible('#headline')
    html = page.inner_html('#headline')
    print(html[:190])

Exercise

Run the code. Trace what each line does.


Identifying HTML Elements

Since the content and design of web pages change frequently, scripts that depend on exact IDs or element types of an HTML page require high maintenance effort. Therefore, in addition to the classic id, Playwright uses generic locator functions that refer to the role of a given element:

get_by_role()
get_by_label()
get_by_title()
get_by_text()

Using the individual locators can be a bit tricky. Fortunately, Playwright takes care of most of the work for you.


The Test Generator

Playwright comes with a Test Generator that records a browser session and generates code from it. This allows even complex test cases to be quickly turned into code.

The test generator can be started with:

playwright codegen www.ecosia.org

Exercise

Create a browser automation using the Test Generator. Clean up the code a bit and run it.


Wait Functions

Before performing an action, Playwright waits for an element to be

  • part of the DOM (the HTML page)

  • visible

  • stable, i.e. not animated

  • responsive to screen events, meaning not hidden behind other elements

  • not “disabled”

Therefore explicit waiting is often not necessary. If you do want to wait explicitly, use the method

page.is_visible("#element-id")

Forms & Drag & Drop

The mechanics of forms follow the same principles as locators for other elements. The only additions are methods like .fill() and .click().

Here is an example of a search query:


from playwright.sync_api import Playwright, sync_playwright, expect


with sync_playwright() as playwright:
    browser = playwright.chromium.launch(headless=False)
    context = browser.new_context()
    page = context.new_page()

    # type query into a search engine
    page.goto("https://www.ecosia.org/")
    page.locator("[data-test-id=\"search-form-input\"]").click()
    page.locator("[data-test-id=\"search-form-input\"]").fill("Hunter und Crohn")
    page.locator("[data-test-id=\"search-form-input\"]").press("Enter")

    # click on a search result
    page.get_by_role("link", name="Hunter & Friends - Webshop").click()

    # visit the target page
    page.get_by_text("Willkommen im Hunter & Friends Webshop").click()
    page.locator("#MainContent").press("Control+c")

    heading = page.get_by_text("Willkommen im")

    # assertion
    expect(heading).to_contain_text("Willkommen im Hunter & Friends Webshop")

    context.close()
    browser.close()