0% found this document useful (0 votes)
4 views44 pages

Playwright Python

Uploaded by

m.mailtorajesh
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views44 pages

Playwright Python

Uploaded by

m.mailtorajesh
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Playwright Python

Complete Beginner's Notes


-created by
Raniya Sherin

21 Sections • All Topics Covered • With Examples

Python 3 Pytest Async/Sync POM CI/CD BDD


Playwright Python — Complete Beginner's Notes Page 2

Table of Contents

Section Title Page

1 Getting Started with Playwright 3

2 Locators — Finding Elements 5

3 Actions — Interacting with Pages 7

4 Events, Waiting & Dialogs 9

5 Authentication & Sessions 11

6 Automated Mail Checker Project 12

7 Pytest — Writing & Running Tests 13

8 pytest-playwright Plugin 15

9 Playwright Tools 16

10 Web-First Assertions 17

11 UI Testing Playground 18

12 Playwright Fixtures 19

13 Page Object Model (POM) 20

14 Network Events 21

15 API Testing 22

16 Optimisation & Speed Tips 23

17 Tips, Tricks & Debugging 24

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 3

18 GitHub API Testing 25

19 Continuous Integration (CI/CD) 26

20 Data-Driven Testing 27

21 Behaviour-Driven Development (BDD) 28

— Quick Reference Cheat Sheet 29

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 4

Section 1

Getting Started with Playwright

This section teaches you everything you need to start using Playwright from scratch.
You will learn what Playwright is, why it is useful, how to install it, and how to write
your very first automation script step by step.

What is Playwright?
Playwright is a free, open-source library created by Microsoft. It allows you to write Python code
that controls a real web browser — just like a human would — clicking buttons, filling forms,
reading text, and navigating pages. It supports three major browsers: Chromium (the engine
behind Chrome), Firefox, and WebKit (the engine behind Safari).

Why use Playwright?


• Web Testing: Automatically test your website to make sure everything works correctly.
• Web Scraping: Collect data from websites automatically without clicking manually.

• Task Automation: Automate boring, repetitive browser tasks such as filling the same form
every day.
• Cross-Browser Support: Run the same script on Chrome, Firefox, and Safari with minimal
changes.
• Fast and Reliable: Playwright waits for pages to load automatically, so your scripts rarely
break.

Installation — Step by Step


Before writing any code you must install Playwright. Open your terminal (Command Prompt on
Windows, Terminal on Mac/Linux) and run the following commands one at a time:

# Step 1: Install the Playwright Python library using pip

pip install playwright


# Step 2: Download the actual browser files (Chromium, Firefox, WebKit)

playwright install

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 5

■ Tip: Always use a virtual environment to keep your project tidy. Run: python -m venv venv then
source venv/bin/activate (Mac/Linux) or venv\Scripts\activate (Windows).

Launching Your First Browser


The basic pattern in Playwright is always the same: launch a browser → open a new page → go
to a URL → do something → close the browser. Here is the simplest possible script:

from playwright.sync_api import sync_playwright


with sync_playwright() as p:
# Launch Chromium browser. headless=False means you can SEE the window.

browser = [Link](headless=False)
# Open a blank new browser tab

page = browser.new_page()
# Navigate to a website

[Link]("[Link]
# Print the title of the page to the terminal

print([Link]())
# Close the browser when done

[Link]()

Understanding headless Mode


• headless=False: The browser window opens visibly on your screen. Great for learning and
debugging.
• headless=True (default): The browser runs in the background without any visible window.
Much faster — use this for automated tests in production.

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 6

Section 2

Locators — Finding Elements on a Page

Before you can click a button or fill in a form, Playwright needs to know WHERE that
element is on the page. A Locator is like a precise address or GPS coordinate for any
element in the HTML. This section covers all the different ways to find elements.

What is a Locator?
Every webpage is made of HTML elements — buttons, links, text boxes, headings, images, etc. A
Locator is a way of telling Playwright "find this specific element for me." Once Playwright finds
the element, you can interact with it (click, type, read, etc.).

■ Note: Always prefer Role, Label, or Text locators. They are more stable and readable than raw CSS
or XPath.

Locator by Role (Most Recommended)


Every HTML element has a "role" — a semantic meaning. A <button> has the role "button", an
<a> tag has the role "link", an <h1> has the role "heading". This is the most reliable way to find
elements because it matches how real users experience the page:

# Click a button whose visible text is "Submit"

page.get_by_role("button", name="Submit").click()
# Click a link whose visible text is "Home"

page.get_by_role("link", name="Home").click()
# Check if a heading is visible

page.get_by_role("heading", name="Welcome").is_visible()
# Find a text input box

page.get_by_role("textbox", name="Search").fill("Python")
Locator by Placeholder and Label
Input fields often have a placeholder (grey hint text) or a label above them. You can use either to
find the field:
# Find by the placeholder text inside the input box

page.get_by_placeholder("Enter your
email").fill("test@[Link]")
# Find by the label text that sits above/beside the input

page.get_by_label("Password").fill("secret123")
Microsoft Playwright • Python Automation • Beginner Friendly
Playwright Python — Complete Beginner's Notes Page 7

Locator by Visible Text


If you can see text on the page, you can find the element containing that text:

# Find any element that contains this text

page.get_by_text("Welcome back!").is_visible()
# exact=True means it must match EXACTLY, not just contain the text

page.get_by_text("Sign In", exact=True).click()

CSS Selectors
CSS selectors are borrowed from web design. They are powerful but slightly more fragile than role-
based locators. Use them when the above options do not work:

# By CSS class name (elements with class="submit-btn")

[Link]("[Link]-btn").click()
# By ID (elements with id="login-form")

[Link]("#login-form").is_visible()
# By HTML attribute

[Link]("input[type=email]").fill("a@[Link]")
# Parent > child hierarchy

[Link]("div > [Link]").inner_text()


# Pseudo-class: the 2nd list item

[Link]("li:nth-child(2)").click()

XPath Locators
XPath is a full path language for navigating HTML trees. It is the most powerful but also the most
verbose. Use as a last resort:

# Find a button whose text is exactly "Login"

[Link]('//button[text()="Login"]').click()
# Find an input with id="username"

[Link]('//input[@id="username"]').fill("admin")
# Find a div that contains the class "error"

[Link]('//div[contains(@class, "error")]').inner_text()
# Find the very last list item on the page

[Link]("//li[last()]").click()

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 8

Section 3

Actions — Interacting with Web Pages

Once you have found an element using a Locator, you need to DO something with it.
Actions are all the things you can do to a web element — clicking, typing, hovering,
selecting from dropdowns, uploading files, and pressing keyboard keys.

Mouse Actions
• click(): A standard left mouse button click.

• dblclick(): A double-click — opens files, selects words in text editors.


• click(button="right"): Right-click — opens context menus.

• hover(): Moves the mouse over an element without clicking — triggers dropdown menus.

• drag_and_drop(): Grabs an element and drops it somewhere else.

[Link]("#btn").click() # left click


[Link]("#btn").dblclick() # double click
[Link]("#btn").click(button="right")# right click
[Link]("#item").hover() # hover over element

# Drag element from #source and drop it onto #target

page.drag_and_drop("#source", "#target")

Text Input
• fill(): Clears the field first, then types the whole text at once. Fast and recommended.

• type(): Types character by character, just like a real keyboard. Useful for testing
autocomplete.
• clear(): Empties the field without typing anything.

# fill is fastest — clears existing text then inserts new text

[Link]("#search").fill("Playwright")
# type simulates real key presses one character at a time

[Link]("#search").type("Playwright")
# clear removes everything from the field

[Link]("#search").clear()

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 9

Checkboxes, Radio Buttons, and Switches


# Tick a checkbox

page.get_by_label("I agree to terms").check()


# Untick a checkbox

page.get_by_label("I agree to terms").uncheck()


# Select a radio button option

page.get_by_label("Male").check()
# Read whether a checkbox is currently ticked (returns True or False)

is_checked = page.get_by_label("I agree to


terms").is_checked()
print(is_checked) # True or False

Dropdown (Select) Menus


# Select by the visible label text

[Link]("#country").select_option("India")
# Select by the hidden value attribute in the HTML

[Link]("#country").select_option(value="IN")
# Select by position (0 = first item, 1 = second item, etc.)

[Link]("#country").select_option(index=2)

Uploading Files
# Upload a single file

[Link]("input[type=file]").set_input_files("[Link]")
# Upload multiple files at once

[Link]("input[type=file]").set_input_files(["[Link]"
, "[Link]"])

Keyboard Shortcuts
[Link]("Enter") # press the Enter key
[Link]("Control+A") # Ctrl+A = select all text
[Link]("Control+C") # Ctrl+C = copy
[Link]("Tab") # move focus to next element
[Link]("Hello World") # type a full string via keyboard

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 10

Section 4

Events, Waiting & Dialogs

Web pages do not always respond instantly. Elements may take time to appear, pop-up
dialogs may interrupt your script, and files may need to be downloaded. This section
explains how Playwright handles all of these situations automatically and how you can
take extra control when needed.

Auto-Waiting — Playwright's Superpower


Most browser automation tools fail because they try to click an element before it finishes loading.
Playwright solves this by automatically waiting for an element to be visible, enabled, and stable
(not moving) before it interacts with it. You almost never need to add a manual sleep() call.

# Playwright waits automatically — no [Link]() needed!

page.get_by_role("button", name="Load Data").click()


# If you want to explicitly wait for some text to appear:

page.get_by_text("Data Loaded").wait_for()

Navigation Waiting
[Link]("[Link]
# Wait until there is no network traffic for 500ms (page is fully loaded)

page.wait_for_load_state("networkidle")
# Wait until the HTML structure (DOM) has finished building

page.wait_for_load_state("domcontentloaded")

Custom Waiting
# Wait for a specific element to appear on the page

page.wait_for_selector("#result")
# Wait a fixed number of milliseconds (2000ms = 2 seconds)

# Use sparingly — better to wait for elements, not time

page.wait_for_timeout(2000)
# Wait until a JavaScript expression becomes true

page.wait_for_function("[Link] === true")

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 11

Listening to Page Events


# Print every [Link]() message from the browser

[Link]("console", lambda msg: print("Console:", [Link]))


# Print any JavaScript errors that occur on the page

[Link]("pageerror", lambda err: print("JS Error:", err))

Handling Pop-up Dialogs (Alert, Confirm, Prompt)


Websites sometimes show browser pop-ups. Playwright lets you handle them automatically by
setting up a listener BEFORE the action that triggers the dialog:

# Accept the dialog (click OK)

[Link]("dialog", lambda dialog: [Link]())


# Dismiss the dialog (click Cancel)

[Link]("dialog", lambda dialog: [Link]())


# For a prompt dialog, type a custom answer and accept

[Link]("dialog", lambda d: [Link]("My Answer"))

Downloading Files
# Use expect_download() to capture the file that gets downloaded
with page.expect_download() as dl_info:

page.get_by_role("button", name="Download Report").click()


download = dl_info.value
download.save_as("my_report.pdf") # save it to your computer

Sync vs Async — Which Should I Use?


• Sync (sync_api): Code runs line by line, one step at a time. Easiest for beginners. Use this
when you are just starting out.
• Async (async_api): Code can handle multiple tasks at the same time. Faster for large
projects that need to run many tests in parallel.

# Async example — note the "async" and "await" keywords

import asyncio
from playwright.async_api import async_playwright
async def main():
async with async_playwright() as p:
browser = await [Link]()
Microsoft Playwright • Python Automation • Beginner Friendly
Playwright Python — Complete Beginner's Notes Page 12

page = await browser.new_page()


await [Link]("[Link]
print(await [Link]())
await [Link]()
[Link](main())

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 13

Section 5

Authentication & Sessions

Many websites require you to log in before you can access their content. Playwright can
automate the login process and, even better, save your login session so you only have to
log in once and reuse it in all future tests.

Automating a Login (Google Example)


You can fill in the email and password fields just like a real user would. Below is an example for
Google Sign-In:

[Link]("[Link]
# Type your email address

page.get_by_label("Email").fill("myemail@[Link]")
page.get_by_role("button", name="Next").click()
# Type your password on the next screen

page.get_by_label("Password").fill("mypassword")
page.get_by_role("button", name="Next").click()
# Now you are logged in!

Saving Your Login Session


Logging in every single test is slow. Playwright can save your cookies and local storage (your
"session") to a file after you log in once, and then reuse that session in all future tests:

# ■■ STEP 1: Log in and save session ■■


context = browser.new_context()
page = context.new_page()
# ... perform your login steps here ...
# Save cookies and localStorage to a file called [Link]

context.storage_state(path="[Link]")
[Link]()
# ■■ STEP 2: Reuse session in future tests ■■
# Load [Link] — Playwright restores your login automatically

context = browser.new_context(storage_state="[Link]")

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 14

page = context.new_page()
# Go directly to the logged-in area — no login form needed!

[Link]("[Link]

■ Tip: Add [Link] to your .gitignore file so you never accidentally share your session credentials on
GitHub.

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 15

Section 6

Automated Mail Checker Project

This real-world project shows you how to combine everything you have learned so far.
You will build a script that automatically opens Gmail, reads your unread emails, and
prints their details to the terminal.

Project File Structure


mail_checker/

■■■ [Link] # your automation script


■■■ [Link] # saved Gmail login session
■■■ [Link] # list of Python packages

Reading Unread Emails


[Link]("[Link]
# Gmail marks unread emails with CSS class "zE"

# We find all of them and count how many there are

unread_emails = [Link]("[Link]")
count = unread_emails.count()
print(f"You have {count} unread emails")

Extracting Sender, Subject and Preview


# Look at the first unread email

first_email = [Link]("[Link]").first
# Extract the sender name

sender = first_email.locator(".yX").inner_text()
# Extract the subject line

subject = first_email.locator(".y6").inner_text()
# Extract the preview text

preview = first_email.locator(".y2").inner_text()
print(f"From: {sender}")
print(f"Subject: {subject}")
print(f"Preview: {preview}")

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 16

Looping Through All Unread Emails

emails = [Link]("table.F tbody tr")


for i in range([Link]()):
email = [Link](i) # get the i-th email row
sender = [Link](".yX").inner_text()

print(f"Email {i+1}: {sender}")

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 17

Section 7

Pytest — Writing and Running Tests

Pytest is the most popular Python testing framework. Instead of just running scripts
manually, Pytest lets you write structured tests that automatically check whether your
website behaves correctly. Playwright integrates seamlessly with Pytest.

What is Pytest?
A test is a small piece of code that checks one specific thing. For example: "After clicking Login,
is the user on the Dashboard page?" Pytest finds all your test functions, runs them, and tells you
which ones passed and which ones failed.

Writing Your First Test


# test_login.py
# File name MUST start with "test_" for Pytest to find it

from playwright.sync_api import Page


def test_login(page: Page):
# 1. Go to the login page

[Link]("[Link]
# 2. Fill in username and password

page.get_by_label("Username").fill("admin")
page.get_by_label("Password").fill("secret")
# 3. Click the Login button

page.get_by_role("button", name="Login").click()
# 4. Check that we ended up on the Dashboard

assert [Link] == "[Link]

Running Tests from the Terminal


pytest # run ALL test files in the folder
pytest test_login.py # run only this specific file
pytest -v # verbose — shows each test name
pytest -k "login" # run only tests whose name contains "login"
pytest -x # stop immediately on the first failure

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 18

Fixtures — Reusable Setup Code


A fixture is a function that sets up something your tests need — like a logged-in browser page —
and then cleans it up automatically afterwards. This avoids copy-pasting setup code into every test:

import pytest
from playwright.sync_api import sync_playwright
@[Link]
def logged_in_page():
with sync_playwright() as p:
browser = [Link]()
page = browser.new_page()
[Link]("[Link]
page.get_by_label("Username").fill("admin")
page.get_by_label("Password").fill("pass")
page.get_by_role("button", name="Login").click()
yield page # hand the ready page to the test
[Link]() # this runs AFTER the test finishes
# Use the fixture by adding it as a parameter

def test_dashboard(logged_in_page):
assert "Dashboard" in logged_in_page.title()

Fixture Scope — How Often is the Fixture Created?


• scope="function" (default): A fresh fixture is created for every single test. Most isolated but
slowest.
• scope="module": One fixture is shared across all tests in the same file.

• scope="session": One fixture is shared across the entire test run. Fastest.

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 19

Section 8

pytest-playwright Plugin

The pytest-playwright plugin is an official add-on that gives you a ready-made "page"
fixture and many useful command-line options, saving you from writing browser setup
code yourself. It is the recommended way to use Playwright with Pytest.

Installation
pip install pytest-playwright
playwright install
Using the Built-in page Fixture
Once installed, you get a "page" fixture for free — just add it as a parameter to your test function
and the plugin handles all browser setup and teardown:
# No browser setup needed — the plugin does it for you!

def test_title(page):
[Link]("[Link]
assert "Example Domain" in [Link]()

Useful Command-Line Options


pytest --headed # show the browser window while tests run
pytest --browser firefox # use Firefox instead of Chromium
pytest --browser webkit # use WebKit (Safari engine)
pytest --slowmo 500 # add 500ms delay between each action (easier to watch)

[Link] — Saving Your Preferred Options

Instead of typing options every time, save your defaults in a [Link] file in your project root:
# [Link]

[pytest]
addopts = --headed --browser chromium
timeout = 30

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 20

Section 9

Playwright Tools — Screenshots, Video, Traces &


Codegen

Playwright comes with powerful built-in tools to help you debug problems, record
videos of test runs, and even automatically generate test code just by clicking around in
the browser.

Take a Screenshot
# Screenshot of the visible portion of the page

[Link](path="[Link]")
# Full-page screenshot including content below the fold

[Link](path="[Link]", full_page=True)
# Screenshot of just one specific element

[Link]("#header").screenshot(path="[Link]")

Record a Video
Tell the context to record a video before you open the page. The video is saved when you close the
context:
context = browser.new_context(record_video_dir="videos/")
page = context.new_page()
# ... perform your actions ...

[Link]() # video is saved to the videos/ folder here

Trace Viewer — Full Debugging Replay


A trace records everything that happened during a test: screenshots of every step, the full HTML
at each moment, and all network requests. When a test fails, you can replay it like a video to see
exactly what went wrong:
context = browser.new_context()
[Link](screenshots=True, snapshots=True)
page = context.new_page()
[Link]("[Link]
# ... do more actions ...

[Link](path="[Link]")

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 21

# Open the trace viewer in your browser:


# playwright show-trace [Link]

Codegen — Auto-Generate Test Code


Codegen is a magic tool: it opens a browser, watches everything you do, and writes the Playwright
code for you in real time. Just interact with the site normally and copy the generated code:

# Run this in your terminal

playwright codegen [Link]


# A browser window and a code panel both open.

# Every click and type you do appears as code on the right side.

■ Tip: Codegen is the fastest way to learn correct selectors for a new website.

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 22

Section 10

Web-First Assertions

Assertions are how you CHECK that your website is behaving correctly. Playwright's
web-first assertions are special — they automatically retry the check up to 5 seconds
before giving up, which means they rarely fail due to timing issues.

Why Web-First Assertions?


A plain Python assert fails immediately. If the page takes 1 second to update, your test fails even
though it would have passed a moment later. Playwright's expect() keeps retrying automatically:
from playwright.sync_api import expect

Page-Level Assertions
# Check the page title

expect(page).to_have_title("Dashboard")
# Check the current URL

expect(page).to_have_url("[Link]

Element State Assertions


expect([Link]("#modal")).to_be_visible() # element is on
screen
expect([Link]("#submit")).to_be_enabled() # button can be
clicked
expect([Link]("#submit")).to_be_disabled() # button is
greyed out
expect([Link]("#modal")).to_be_hidden() # element is not
visible

Text and Content Assertions


# Element must contain EXACTLY this text

expect([Link]("h1")).to_have_text("Welcome!")
# Element must contain this text SOMEWHERE inside it

expect([Link](".message")).to_contain_text("success")

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 23

Input and Attribute Assertions


# Check an HTML attribute

expect([Link]("img")).to_have_attribute("alt", "Logo")
# Check the current value inside an input field

expect(page.get_by_label("Email")).to_have_value("test@email.c
om")
# Check a checkbox is ticked

expect(page.get_by_label("Remember me")).to_be_checked()
# Check a dropdown's selected value
expect([Link]("#country")).to_have_value("IN")

■ Note: All expect() assertions wait up to 5 seconds by default before failing. You can customise this:
expect(locator, timeout=10000).

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 24

Section 11

UI Testing Playground — Practice Challenges

Ui [Link] is a free website specifically designed to challenge your


Playwright skills. It presents tricky real-world situations you will encounter on real
websites. Here is how to solve each challenge.

Dynamic ID — ID Changes Every Page Load


Never rely on an ID that changes. Use visible text or role instead.

# BAD: [Link]("#btn-12345").click() <- ID changes every time!


# GOOD: use the visible button text instead

page.get_by_role("button", name="Button with Dynamic


ID").click()

Hidden Layer — Another Element is Blocking the Click


Wait for the blocking overlay to disappear, or force the click.

page.wait_for_selector("#hidingLayer", state="hidden") # wait for


blocker to go

[Link]("#greenButton").click(force=True) # or force it

Load Delay — Element Appears After a Delay


Playwright waits automatically, but you can increase the timeout for slow pages.

# Increase timeout to 10 seconds for very slow elements

[Link]("#ajaxButton").click(timeout=10000)

AJAX — Content Loads Asynchronously After a Click


Click the button, then wait for the new content to appear.

[Link]("#ajaxButton").click()
page.wait_for_selector(".bg-success") # wait for result
text = [Link](".bg-success p").inner_text()
print(text)

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 25

Scrollbars — Element is Off-Screen


Scroll the element into view before clicking.

[Link]("#scrollBtn").scroll_into_view_if_needed()
[Link]("#scrollBtn").click()

Progress Bar — Wait Until Completion


Use wait_for_function to poll the value and stop at the right moment.

[Link]("#startButton").click()
page.wait_for_function(
'[Link]("#progressBar")
.getAttribute("aria-valuenow") >= 75'
)
[Link]("#stopButton").click()

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 26

Section 12

Playwright Fixtures — Advanced Browser Setup

Fixtures control how browsers are created and shared across tests. Choosing the right
scope balances isolation (each test is independent) against speed (sharing a browser is
faster).

Function Scope — One Browser Per Test (Most Isolated)


@[Link]
def page():
with sync_playwright() as p:
browser = [Link]()
page = browser.new_page()
yield page
[Link]() # browser closes after EACH test

Session Scope — One Browser for ALL Tests (Fastest)


@[Link](scope="session")
def browser_session():
with sync_playwright() as p:
browser = [Link]()
yield browser
[Link]() # browser closes only at the END of all tests

Cross-Browser Testing
# Run the same test on multiple browsers automatically

@[Link](params=["chromium", "firefox", "webkit"])


def cross_browser(request):
with sync_playwright() as p:
browser = getattr(p, [Link]).launch()
yield browser.new_page()
[Link]()

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 27

Browser Launch Arguments


browser = [Link](
headless=False,
slow_mo=100, # add 100ms pause between every action
args=["--start-maximized"]# start the browser in full screen
)

# Set viewport size and locale

context = browser.new_context(
viewport={"width": 1280, "height": 720},
locale="en-IN",
timezone_id="Asia/Kolkata"
)

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 28

Section 13

Page Object Model (POM)

The Page Object Model is a design pattern that makes your tests cleaner, easier to read,
and much easier to maintain. Instead of putting all your locators and actions directly
inside each test, you create a separate Python class for each page of your website.

Why Use POM?


• Cleaner tests: Test functions read like plain English — no messy locator strings.

• Easy maintenance: If a button changes, you update it in ONE place (the class), not in every
test that uses it.
• Reusability: The same page class can be used by dozens of different tests.

Creating a Page Class


# pages/login_page.py

class LoginPage:
def __init__(self, page):
[Link] = page
# Define locators as class attributes

self.username_field = page.get_by_label("Username")
self.password_field = page.get_by_label("Password")
self.login_button = page.get_by_role("button", name="Login")
def navigate(self):
"""Go to the login page."""

[Link]("[Link]
def login(self, username, password):
"""Fill in credentials and click login."""

self.username_field.fill(username)
self.password_field.fill(password)
self.login_button.click()

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 29

Using POM in Tests


# test_login.py

from pages.login_page import LoginPage


from playwright.sync_api import expect

def test_valid_login(page):
login = LoginPage(page) # create the page object
[Link]() # go to login page

[Link]("admin", "secret") # perform login


# Verify we reached the dashboard

expect(page).to_have_url("[Link]

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 30

Section 14

Network Events — Monitoring & Intercepting


Traffic

Playwright lets you listen to every HTTP request and response that the browser makes.
You can also intercept requests to block certain resources, speed up tests, or return fake
data for testing purposes.

Listening to Requests and Responses


# Print every URL the browser requests

[Link]("request", lambda req: print("Request:",


[Link]))
# Print every response the browser receives
[Link]("response", lambda resp: print("Response:", [Link], [Link]))

Blocking Unwanted Requests (Speed Optimisation)


# Block all PNG and JPG images — makes tests faster

[Link]("**/*.png", lambda route: [Link]())


[Link]("**/*.jpg", lambda route: [Link]())

Intercepting API Calls


def handle_api(route):
print("API call intercepted:", [Link])
route.continue_() # let the real request through
[Link]("**/api/**", handle_api)

Mocking API Responses — Returning Fake Data


Instead of calling a real server, you can intercept an API request and return fake data. This is useful
for testing edge cases or working without a backend:

def mock_user(route):
[Link](
status=200,
content_type="application/json",
body='{"user": "FakeUser", "id": 99}'

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 31

[Link]("**/api/user", mock_user)
# Now when the page calls /api/user, it gets fake data

[Link]("[Link]

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 32

Section 15

API Testing with Playwright


Playwright is not only for browser automation — it also has a powerful HTTP client
built in for testing REST APIs directly without opening a browser. You can make GET,
POST, PUT, and DELETE requests and assert on the responses.

Making a Basic API Request


from playwright.sync_api import sync_playwright
with sync_playwright() as p:
# Create an API request context (no browser needed)

api = [Link].new_context()
# Make a GET request

response =
[Link]("[Link]
print([Link]) # 200
print([Link]()) # {"id": 1, "title": ...}

CRUD Operations — GET, POST, PUT, DELETE


api =
[Link].new_context(base_url="[Link]
[Link]")
# GET — Read a resource

r = [Link]("/posts/1")
print([Link]()["title"])
# POST — Create a new resource

r = [Link]("/posts", data={"title": "My Post", "body":


"Content", "userId": 1})
print([Link]) # 201 Created
# PUT — Update an existing resource

r = [Link]("/posts/1", data={"title": "Updated Title"})


# DELETE — Remove a resource

r = [Link]("/posts/1")

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 33

assert [Link] == 200


Query String Parameters
# Get posts by userId=1, limited to 5 results

r = [Link]("/posts", params={"userId": 1, "_limit": 5})


# This sends: GET /posts?userId=1&_limit=5

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 34

Section 16

Optimisation & Speed Tips


As your test suite grows, speed becomes important. This section covers techniques to
make your Playwright tests run significantly faster without sacrificing quality.

Block Unnecessary Resources


Images, fonts, and stylesheets are not needed for most tests. Blocking them can cut page load time
by 50% or more:
def block_resources(route):
if [Link].resource_type in ["image", "font",
"stylesheet"]:
[Link]() # do not load this
else:
route.continue_() # load everything else normally
[Link]("**/*", block_resources)

Disable JavaScript
If you only need to read static HTML content, disabling JavaScript speeds up page loads:

context = browser.new_context(java_script_enabled=False)
page = context.new_page()
[Link]("[Link] # loads without executing any
JavaScript

Run Tests in Parallel


By default Pytest runs tests one by one. With pytest-xdist you can run many tests simultaneously,
using all your CPU cores:

# Install the parallel runner

pip install pytest-xdist


# Run with 4 parallel workers

pytest -n 4
# Automatically use all available CPU cores

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 35

pytest -n auto
■ Tip: Parallel tests MUST be independent. Each test should not rely on data created by another test.

Section 17

Tips, Tricks & Debugging


This section collects the most useful debugging techniques, CLI shortcuts, and
advanced features that will save you hours of frustration.

Essential Pytest CLI Options


pytest -v # verbose — show each test name and result
pytest -s # show print() output in the terminal
pytest --tb=short # shorter, readable error tracebacks
pytest -x # stop on the first failing test
pytest --lf # re-run only the tests that failed last time
pytest -k "login or signup" # filter tests by name keyword

Python Debugger (pdb) — Pause and Inspect


If a test is failing and you cannot figure out why, you can pause execution and inspect the browser
state manually:

def test_debug(page):
[Link]("[Link]
import pdb; pdb.set_trace() # pauses here
# In terminal: type "n" for next line, "c" to continue, "q" to quit

Device Emulation — Test on Mobile


with sync_playwright() as p:
# Use a pre-defined device profile

iphone = [Link]["iPhone 13"]


context = [Link]().new_context(**iphone)
page = context.new_page()
[Link]("[Link] # renders as if on an iPhone 13

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 36

Evaluate JavaScript in the Browser


# Read the page title via JavaScript

title = [Link]("[Link]")
# Count how many list items are on the page

count =
[Link]('[Link]("li").length')

# Pass a Python value into JavaScript and get a result back

result = [Link]("(x) => x * 2", 21) # returns 42

`Generate HTML Test Reports


pip install pytest-html
pytest --html=[Link] --self-contained-html
# Open [Link] in your browser to see a visual test report

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 37

Section 18

GitHub API Testing

Combining Playwright's API client with GitHub's REST API lets you write tests that
create repositories, manage issues, and verify your CI pipeline — all from Python.

Setting Up Your GitHub Token Safely


Never paste your token directly in code — store it as an environment variable:
import os
# Read the token from the environment (set it in your terminal first)

# export GITHUB_TOKEN=ghp_yourtokenhere

token = [Link]["GITHUB_TOKEN"]

Authorised API Context


api = [Link].new_context(
base_url="[Link]
extra_http_headers={
"Authorization": f"token {token}",
"Accept": "application/[Link].v3+json"
}
)

Sample GitHub API Tests


def test_create_repo(api_context):
r = api_context.post("/user/repos", data={
"name": "my-test-repo",
"private": True
})
assert [Link] == 201
assert [Link]()["name"] == "my-test-repo"
def test_delete_repo(api_context):
r = api_context.delete("/repos/myuser/my-test-repo")
assert [Link] == 204

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 38

Section 19

Continuous Integration (CI/CD) with GitHub


Actions

CI automatically runs your Playwright tests every time you push code to GitHub. This
means bugs are caught immediately — before they reach production. GitHub Actions is
free for public repositories and provides this feature out of the box.

How CI Works
• You push code to GitHub (git push).
• GitHub Actions automatically detects the push.

• It spins up a virtual computer, installs your dependencies, and runs your tests.
• You see a green tick (passed) or red cross (failed) on your pull request.

• If tests fail, you fix the bug before merging.

GitHub Actions Workflow File


# .github/workflows/[Link]

name: Playwright Tests


on: [push, pull_request] # run on every push and pull request
jobs:
test:
runs-on: ubuntu-latest
steps:
# 1. Download your repository code

- uses: actions/checkout@v3
# 2. Install Python

- uses: actions/setup-python@v4
with:
python-version: "3.11"
# 3. Install Playwright and Pytest

- run: pip install pytest playwright pytest-playwright


# 4. Download the browsers

- run: playwright install --with-deps

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 39

# 5. Run the tests!

- run: pytest
Using Secrets Safely in CI

# In GitHub: Settings > Secrets > Actions > New Secret


# Add: Name = GITHUB_TOKEN, Value = your_actual_token

# Reference it in your workflow file:

env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 40

Section 20

Data-Driven Testing

Data-driven testing means running the SAME test with DIFFERENT inputs
automatically.
Instead of writing 10 nearly identical tests, you write 1 test and provide 10 sets of data.
Pytest's parametrize decorator makes this simple.

Using [Link]
import pytest
@[Link]("username, password,
expected_message", [
("admin", "correct", "Dashboard"), # valid login
("admin", "wrongpass", "Invalid credentials"), # wrong password
("nouser", "anypass", "User not found"), # unknown user
])
def test_login(page, username, password, expected_message):
[Link]("[Link]
page.get_by_label("Username").fill(username)
page.get_by_label("Password").fill(password)
page.get_by_role("button", name="Login").click()
expect([Link](".message")).to_contain_text(expected_mess
age)

What the Output Looks Like


pytest -v
# Output:

# test_login[admin-correct-Dashboard] PASSED

# test_login[admin-wrongpass-Invalid...] PASSED

# test_login[nouser-anypass-User not found] PASSED

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 41

Section 21

Behaviour-Driven Development (BDD)

BDD is a way of writing tests in plain English so that even non-developers (project
managers, testers, business analysts) can read and understand them. It uses a specific
format called Gherkin with Given / When / Then steps.

What is the Given / When / Then Format?


• Given: The starting state — what is true before the action. Example: "Given I am on the
login page"
• When: The action the user takes. Example: "When I enter my username and password"
• Then: The expected result. Example: "Then I should see the dashboard"

Setup
pip install pytest-bdd

Feature File (Plain English Scenario)


# features/[Link]

Feature: User Login


Scenario: Successful login with valid credentials
Given I am on the login page
When I enter "admin" and "secret"
Then I should see the dashboard

Step Definitions (Python Code that Runs Each Step)


# test_login_bdd.py

from pytest_bdd import given, when, then, scenario


from playwright.sync_api import expect
@scenario("features/[Link]", "Successful login with
valid credentials")
def test_login(): pass

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 42

@given("I am on the login page")


def go_to_login(page):
[Link]("[Link]

@when('I enter "admin" and "secret"')


def enter_credentials(page):
page.get_by_label("Username").fill("admin")
page.get_by_label("Password").fill("secret")

page.get_by_role("button", name="Login").click()
@then("I should see the dashboard")
def check_dashboard(page):
expect(page).to_have_url("[Link]

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 43

Quick Reference Cheat Sheet

A handy one-page summary of the most commonly used Playwright commands. Keep
this as a bookmark or print it out for your desk.

Task Code

Launch browser (visible) [Link](headless=False)

Open a new tab browser.new_page()

Go to a URL [Link]("[Link]

Click button by role page.get_by_role("button", name="X").click()

Fill an input field page.get_by_label("Email").fill("a@[Link]")

Get element text [Link]("h1").inner_text()

Wait for element to appear page.wait_for_selector("#id")

Take a screenshot [Link](path="[Link]")

Take full-page screenshot [Link](path="[Link]", full_page=True)

Assert page title expect(page).to_have_title("Home")

Assert element visible expect([Link]("#el")).to_be_visible()

Assert element text expect([Link]("p")).to_have_text("Hi")

Mock an API endpoint [Link]("**/api", lambda r: [Link](...))

Block image loading [Link]("**/*.png", lambda r: [Link]())

Check a checkbox page.get_by_label("I agree").check()

Select a dropdown option [Link]("#dd").select_option("India")

Upload a file [Link]("input[type=file]").set_input_files("[Link]")

Accept a dialog popup [Link]("dialog", lambda d: [Link]())

context = [Link]().new_context(**[Link]["iPhone
Emulate iPhone 13 13"])

Run JavaScript [Link]("[Link]")

Microsoft Playwright • Python Automation • Beginner Friendly


Playwright Python — Complete Beginner's Notes Page 44

Run all tests pytest -v --headed

Run specific file pytest test_login.py -v

Run in parallel pytest -n auto

Generate code automatically playwright codegen [Link]

View a trace file playwright show-trace [Link]

Generate HTML report pytest --html=[Link] --self-contained-html

Save login session context.storage_state(path="[Link]")

Reuse login session browser.new_context(storage_state="[Link]")

Task Code

Record a video browser.new_context(record_video_dir="videos/")

Block all images+fonts [Link]() if resource_type in ["image","font"]

Microsoft Playwright • Python Automation • Beginner Friendly

You might also like