Manuals / Playwright with Python / Ch 21

Part 3 · Test Structure & FrameworkIntermediate55 min read

14. Page Object Model (POM)

Playwright with Python · 244 pages source format

Why POM, folder structure Without POM, locators get written directly inside test functions — meaning if the UI changes (a button's text, an ID), you have to hunt down and fix every test that touches that element. POM solves this by centralizing each page's locators and actions into a dedicated class, so a UI change means fixing one class, not dozens of tests.

What you'll learn

  • Why POM, folder structure Without POM, locators get written directly inside test
  • POM solves this by centralizing each page's locators and actions into a dedicate
  • project/ ├── pages/ │ ├── base_page.py

Overview

Why POM, folder structure Without POM, locators get written directly inside test functions — meaning if the UI changes (a button's text, an ID), you have to hunt down and fix every test that touches that element. POM solves this by centralizing each page's locators and actions into a dedicated class, so a UI change means fixing one class, not dozens of tests.

project/

├── pages/

│ ├── base_page.py

│ ├── login_page.py

│ └── dashboard_page.py

├── tests/

│ ├── test_login.py

│ └── test_dashboard.py

└── conftest.py Base Page class A BasePage holds behavior common to every page — navigation, generic waits — so individual page classes don't repeat it. python

Interactive study board
OverviewDrag stickies · tap for tips
Study mapDrag stickies · tap for tipsKeep it shortdrag · tap →Name the waitdrag · tap →Scope locatorsdrag · tap →Trace when stuckdrag · tap →One browser firstdrag · tap →Isolate statedrag · tap →Assert the UIdrag · tap →Retry wiselydrag · tap →Seed datadrag · tap →Close the loopdrag · tap →Keep it shortdrag · tap →Name the waitdrag · tap →Scope locatorsdrag · tap →Trace when stuckdrag · tap →One browser firstdrag · tap →Isolate statedrag · tap →Pathwise hackdrag · tap →Page under testdrag · tap →Multi-browserdrag · tap →Automation pathdrag · tap →Tooling nodedrag · tap →
Clear?

pages/base_page.py

self.page = page

BasePage.__init__(self, page) What it does: Stores a reference to the Playwright page object so every method in the class (and its subclasses) can use it. Types/params:

Pointers: Every page class should inherit from this and call

Run / study this snippet
def navigate(self, path):
Interactive study board
pages/base_page.pyDrag stickies · tap for tips
Study mapDrag stickies · tap for tipsKeep it shortdrag · tap →Name the waitdrag · tap →Scope locatorsdrag · tap →Trace when stuckdrag · tap →One browser firstdrag · tap →Isolate statedrag · tap →Assert the UIdrag · tap →Retry wiselydrag · tap →Seed datadrag · tap →Close the loopdrag · tap →Keep it shortdrag · tap →Name the waitdrag · tap →Scope locatorsdrag · tap →Trace when stuckdrag · tap →One browser firstdrag · tap →Isolate statedrag · tap →Pathwise hackdrag · tap →Page under testdrag · tap →Multi-browserdrag · tap →Automation pathdrag · tap →Tooling nodedrag · tap →
Clear?

pages/login_page.py

self.username_input = page.get_by_label("Username")

self.password_input = page.get_by_label("Password")

self.login_button = page.get_by_role("button", name="Log in")

python

login_page = LoginPage(page)

LoginPage.login(self, username, password) (example custom page method — pattern, not a Playwright API) What it does: Encapsulates the full "log in" user flow as one method call, hiding the individual locator/action steps from the test itself. Types/params:

Pointers: The test file itself should read almost like plain English (login_page.login(...)) — if a test file is full of raw locators and .fill()/.click() calls, that's a signal POM isn't being followed consistently.

  • username (string, required)
  • password (string, required)
Run / study this snippet
def login(self, username, password):
Interactive study board
pages/login_page.pyDrag stickies · tap for tips
Study mapDrag stickies · tap for tipsKeep it shortdrag · tap →Name the waitdrag · tap →Scope locatorsdrag · tap →Trace when stuckdrag · tap →One browser firstdrag · tap →Isolate statedrag · tap →Assert the UIdrag · tap →Retry wiselydrag · tap →Seed datadrag · tap →Close the loopdrag · tap →Keep it shortdrag · tap →Name the waitdrag · tap →Scope locatorsdrag · tap →Trace when stuckdrag · tap →One browser firstdrag · tap →Isolate statedrag · tap →Pathwise hackdrag · tap →Page under testdrag · tap →Multi-browserdrag · tap →Automation pathdrag · tap →Tooling nodedrag · tap →
Clear?

Checklist