How to write E2E tests with Python
Technical Team Lead at HedgeServ Bulgaria
Rositsa Kotseva
A library that is used as a general purpose browser automation tool. It provides a powerful set of APIs to automate the web applications testing.
─$ pip install pytest-playwright
─$ playwright install
─$ touch test_playwright.py
─$ pytest
from playwright.sync_api import Page, expect
def test_playwright_python_page_title(page: Page) -> None:
page.goto("https://playwright.dev/python/")
assert page.title() == "Fast and reliable end-to-end testing for modern web apps | Playwright Python"
def test_get_started_link(page: Page) -> None:
page.goto("https://playwright.dev/python/")
# Click the get started link.
page.get_by_role("link", name="Get started").click()
# Expects page to have a heading with the name of Installation.
expect(page.get_by_role("heading", name="Installation")).to_be_visible()
def test_playwright_library_link(page: Page) -> None:
page.goto("https://playwright.dev/python/docs/intro")
# Click the Playwright library link
page.get_by_role("link", name="Playwright library").click()
assert page.url == 'https://playwright.dev/python/docs/library'
╰─$ pytest test_playwright.py 1 ↵
================================================================ test session starts ===============================================================================================
platform linux -- Python 3.10.7, pytest-8.2.1, pluggy-1.5.0
rootdir: /home/kamen/workshop/code
plugins: playwright-0.5.0, base-url-2.1.0
collected 3 items
test_playwright.py ... [100%]
================================================================= 3 passed in 1.26s ================================================================================================
def test_with_screenshot(playwright: Playwright):
chromium_engine = playwright.chromium
browser = chromium_engine.launch()
context = browser.new_context()
page = context.new_page()
page.goto("https://hackbulgaria.com")
page.screenshot(path="screenshot_hb.png")
locator = page.get_by_role("link", name="Запиши се")
expect(locator).to_be_visible()
browser.close()
locator = page.get_by_role("button", name="Log in")
page.get_by_text("Welcome!")
page.get_by_label("Password")
page.get_by_placeholder("name@example.com")
page.get_by_alt_text("playwright logo")
page.get_by_title("Elements count")
page.get_by_test_id("some data test id")
page.locator("css=button")
page.locator("xpath=//button")
locator = page.get_by_role("button", name="Log in")
locator.click()
locator.check()
locator.hover()
locator.fill()
locator.focus()
...select_option()
...uncheck()
...etc
locator = page.get_by_role("button", name="Log in")
expect(locator).to_be_enabled()
expect(locator).to_be_visible()
expect(locator).to_be_checked()
expect(locator).to_be_contain_text()
expect(locator).to_have_value()
expect(locator).to_have_text()
....etc
Function scope: created when requested in a test function and destroyed when the test ends.
context
: New browser context for a test.page
: New browser page for a test.
new_context
: Allows creating different browser contexts for a test. Useful for multi-user scenarios
Session scope: created when requested in a test function and destroyed when all tests end.
playwright
: Playwright instance.
browser_type
: BrowserType instance of the current browser.
browser
: Browser instance launched by Playwright.
browser_name
: Browser name as string.browser_channel
: Browser channel as string.is_chromium
, is_webkit
, is_firefox
: Booleans for the browser types.@pytest.fixture(scope="session")
def api_request_context(
playwright: Playwright,
) -> Generator[APIRequestContext, None, None]:
headers = {
"Accept": "XXXXXX",
"Authorization": f"token {SOME_API_TOKEN}",
}
request_context = playwright.request.new_context(
base_url="https://api.some_webpage.com", extra_http_headers=headers
)
yield request_context
request_context.dispose()
def test_create_new_report(api_request_context: APIRequestContext) -> None:
data = {
"report_name": "Report 1"
}
new_report = api_request_context.post(f"/reports/create, data=data)
assert new_report.ok
all_reports = api_request_context.get(f"/reports/all")
assert reports.ok
╰─$ playwright codegen hackbulgaria.com
import re
from playwright.sync_api import Playwright, sync_playwright, expect
def run(playwright: Playwright) -> None:
browser = playwright.chromium.launch(headless=False)
context = browser.new_context()
page = context.new_page()
page.goto("https://www.hackbulgaria.com/")
page.get_by_role("link", name="Запиши се").get_by_role("button").click()
page.get_by_role("link", name="Кариеростарт").nth(1).click()
page.get_by_role("button", name="Разгледай всички възможности (40) arrow").click()
page.goto("https://www.hackbulgaria.com/career-start/opportunities?activeLocationIds=%5B%22D20lRYGtS6q9Xvu9ewi6hg%22%5D")
page.goto("https://www.hackbulgaria.com/career-start/opportunities?activeLocationIds=%5B%22D20lRYGtS6q9Xvu9ewi6hg%22%2C%22aBa1wbURTZWUHz8BXKn4Og%22%5D")
page.get_by_role("link", name="Junior-friendly позиции Junior Full-Stack Developer with Laravel във").click()
with page.expect_popup() as page1_info:
page.get_by_role("button", name="Научи повече").click()
page1 = page1_info.value
page.get_by_role("link", name="Workshops").nth(1).click()
page.get_by_role("link", name="Събития").nth(1).click()
with page.expect_popup() as page2_info:
page.get_by_role("link", name="Facebook страницата на").click()
page2 = page2_info.value
# ---------------------
context.close()
browser.close()
with sync_playwright() as playwright:
run(playwright)
pytest --tracing on
playwright show-trace test-results/test-playwright-py-test-playwright-library-link-chromium/trace.zip
10.9k stars, 825 forks, around 1.2k closed issues