1. 環境說明
- 操作系統:macOS 11.7
- Python:3.10.6
2. 安裝
2.1. 創建測試環境
mkdir playwright-demo
cd playwright-demo/
python3 -m venv venv
# 安裝 Pytest 插件
venv/bin/pip3 install pytest-playwright
# 安裝需要的瀏覽器
venv/bin/playwright install
2.2. 添加樣例測試
在當前工作目錄或子目錄內部,創建test_my_application.py文件,其內容如下:
import re
from playwright.sync_api import Page, expect
def test_homepage_has_Playwright_in_title_and_get_started_link_linking_to_the_intro_page(page: Page):
page.goto(“Fast and reliable end-to-end testing for modern web apps | Playwright”)
# Expect a title “to contain” a substring.
expect(page).to_have_title(re.compile(“Playwright”))
# create a locator
get_started = page.locator(“text=Get started”)
# Expect an attribute “to be strictly equal” to the value.
expect(get_started).to_have_attribute(“href”, “/docs/intro”)
# Click the get started link.
get_started.click()
# Expects the URL to contain intro.
expect(page).to_have_url(re.compile(“.*intro”))
2.3. 運行樣例測試
默認情況下,測試運行在 chromium 上,可通過 CLI 選項進行配置,測試以 Headless 模式運行。測試結果和測試日志被展示在終端中。
venv/bin/pytest
3. 編寫測試
Playwright 斷言(assertion)是專門為動態網頁創建的。檢查會自動重試,直到滿足必要的條件。Playwright 自帶 auto-wait,這意味著它在執行操作之前等待元素變為可操作的(actionable)。Playwright 提供 expect 函數來寫斷言。
下面的樣例測試展示了如何寫使用斷言、定位器(locator)和選擇器(selector)的測試。
import re
from playwright.sync_api import Page, expect
def test_homepage_has_Playwright_in_title_and_get_started_link_linking_to_the_intro_page(page: Page):
page.goto(“Fast and reliable end-to-end testing for modern web apps | Playwright”)
# Expect a title “to contain” a substring.
expect(page).to_have_title(re.compile(“Playwright”))
# create a locator
get_started = page.locator(“text=Get started”)
# Expect an attribute “to be strictly equal” to the value.
expect(get_started).to_have_attribute(“href”, “/docs/intro”)
# Click the get started link.
get_started.click()
# Expects the URL to contain intro.
expect(page).to_have_url(re.compile(“.*intro”))
3.1. 斷言
Playwright 提供 expect 函數,它會一直等待,直到滿足預期條件。
import re
from playwright.sync_api import expect
expect(page).to_have_title(re.compile(“Playwright”))
3.2. 定位器
定位器(Locators)是 Playwright 的自動等待和重試能力的核心部分。定位器表示一種隨時在網頁上查找元素的方法,用于在元素上執行諸如 .click、.fill 之類的操作。可以使用 page.locator(selector, **kwargs) 方法創建自定義的定位器。
from playwright.sync_api import expect
get_started = page.locator(“text=Get started”)
expect(get_started).to_have_attribute(“href”, “/docs/installation”)
get_started.click()
選擇器(Selectors)是用于創建定位器的字符串。Playwright 支持許多不同的選擇器,比如 Text、CSS、XPath 等。通過 in-depth guide 文檔,了解更多關于可用的選擇器以及如何進行選擇的信息。
from playwright.sync_api import expect
expect(page.locator(“text=Installation”)).to_be_visible()
3.3. 測試隔離
Playwright Pytest 插件基于 test fixture(比如 built in page fixture)的概念,它會被傳給你的測試。由于瀏覽器上下文,在測試之間,頁面(page)彼此隔離,這相當于開啟新的瀏覽器行為,每個測試獲得新環境,即使在一個瀏覽器中運行多個測試時,也是如此。
from playwright.sync_api import Page
def test_basic_test(page: Page):
# …
3.4. 使用測試鉤子
你可以使用各種各樣的 fixtures 來在你的測試之前或之后執行代碼,以及在它們之間共享對象。函數(function)作用域的 fixture 具有 beforeEach/afterEach 一樣的自動使用行為。模塊(module)作用域的 fixture 具有 beforeAll/afterAll 一樣的自動使用行為,它會在所有測試之前和所有測試之后運行。
import pytest
from playwright.sync_api import Page, expect
@pytest.fixture(scope=”function”, autouse=True)
def before_each_after_each(page: Page):
print(“beforeEach”)
# Go to the starting url before each test.
page.goto(“Fast and reliable end-to-end testing for modern web apps | Playwright”)
yield
print(“afterEach”)
def test_main_navigation(page: Page):
# Assertions use the expect API.
expect(page).to_have_url(“Fast and reliable end-to-end testing for modern web apps | Playwright”)
4. 運行測試
你可以運行單個測試、一組測試或全部測試。測試可以運行在一種或多種瀏覽器上。默認情況下,測試以 headless 方式運行,這意味著在運行測試時,不會打開瀏覽器窗口,可以在終端中看到結果。通過使用 –headed 標記,可以以 headed 模式運行測試。
– 在 Chromium 上運行測試
pytest
– 運行單個測試文件
pytest test_login.py
– 運行一組測試文件
pytest tests/todo-page/ tests/landing-page/
– 使用函數名運行測試
pytest -k “test_add_a_todo_item”
– 以有頭(headed)模式運行測試
pytest –headed test_login.py
– 在指定的瀏覽器上運行測試
pytest test_login.py –browser webkit
– 在多種瀏覽器上運行測試
pytest test_login.py –browser webkit –browser firefox
– 并行運行測試
pytest –numprocesses auto
(假定已安裝 pytest-xdist,查看 here 獲取更多信息。)
4.1. 運行測試
因為 Playwright 運行在 Python 中,所以可以使用 debugger 調試它。Playwright 自帶 Playwright Inspector,它允許你逐步通過 Playwright API 調用,查看它們的調試日志,以及探索選擇器(selectors)。
PWDEBUG=1 pytest -s

查看我們的調試指南(debugging guide)來了解關于 Playwright Inspector 以及使用瀏覽器開發者工具(Browser Developer tools)進行調試的更多信息。
5. 測試生成器
Playwright 具有開箱即用的生成測試的能力,這是快速開始測試的好方法。它會打開兩個窗口,一個是瀏覽器窗口,通過它你可以與希望測試的網站進行交互,另一個是 Playwright Inspector 窗口,通過它你可以錄制測試、拷貝測試、清除測試以及改變測試的語言。
你將學習:
– How to generate tests with Codegen
5.1. 運行代碼生成器(Codegen)
playwright codegen Fast and reliable end-to-end testing for modern web apps | Playwright
運行 codegen,然后在瀏覽器中執行操作。Playwright 會為用戶的交互生成代碼。Codegen 會嘗試生成彈性的基于文本的選擇器。

當你完成與頁面的交互時,按下record按鈕停止錄制,使用copy按鈕把生成的代碼拷貝到編輯器。

使用 clear 按鈕清除代碼,重新開始錄制。完成時,關閉 Playwright Inspector 窗口,或停止終端命令。
要了解有關生成測試的更多信息,請查看 Codegen 的詳細指南。
6. 追蹤查看器(Trace Viewer)
Playwright 追蹤查看器是一個 GUI 工具,它使你可以探查你的測試中記錄的 Playwright 追蹤,你可以在測試的每個操作中來回移動,可視化地查看每個操作期間正在發生什么。
你將學習:
– 如何記錄追蹤
– 如何打開 HTML 報告
– 如何打開追蹤查看器
6.1. 記錄追蹤
像下面一樣使用 browser_context.tracing API 記錄追蹤:
browser = chromium.launch()
context = browser.new_context()
# Start tracing before creating / navigating a page.
context.tracing.start(screenshots=True, snapshots=True, sources=True)
page.goto(“Fast and reliable end-to-end testing for modern web apps | Playwright”)
# Stop tracing and export it into a zip archive.
context.tracing.stop(path = “trace.zip”)
這將記錄追蹤,并把它放到名稱為trace.zip的文件中。
6.2. 打開追蹤
你可以使用 Playwright CLI 打開保存的追蹤。
playwright show-trace trace.zip
6.3. 查看追蹤
通過單擊每個操作或使用時間軸懸停來查看測試的追蹤,以及查看操作前后的頁面狀態。在測試的每個步驟期間查看日志、源和網絡。追蹤查看器創建 DOM 快照,因此你可以與它進行交互,打開開發者工具(devtools)等。

要了解更多信息,請查看 Trace Viewer 的詳細指南。
7. Pytest 插件參考
Playwright 提供 Pytest 插件來編寫端到端的測試。如果想要使用它,請參考 getting started guide。
7.1. 用法
使用 Pytest CLI 運行測試:
pytest –browser webkit –headed
如果你想自動地添加 CLI 參數,請使用 pytest.ini 文件。
7.2. CLI 參數
- – –headed:以有頭模式運行測試(默認:無頭)
- – –browser:用不同的瀏覽器 chromium、firefox、webkit 運行測試。可以指定多次(默認:所有瀏覽器)
- – –browser-channel:使用的 Browser channel
- – –slow-mo:使用慢動作運行測試
- – –device:模擬的設備(Device)
- – –output:用于測試生成的制品(aritifact)的目錄(默認:test-results)
- – –tracing:是否為每次測試記錄追蹤(trace)。on、off 或 retain-on-failure(默認:off)
- – –video:是否為每次測試錄制視頻。on、off 或 retain-on-failure(默認:off)
- – –screenshot:是否在每次測試后,自動地捕獲截屏。on, off, or only-on-failure (默認:off)
7.3. Fixture
該插件給 pytest 配置 Playwright 特定的 fixture(fixtures for pytest)。為使用這些 fixture,使用 fixture 名稱作為測試函數的參數。
def test_my_app_is_working(fixture_name):
# Test using fixture_name
# …
函數作用域:這些 fixture 在測試函數請求時創建,在測試結束時銷毀。
- – context:用于測試的新瀏覽器上下文(browser context)
- – page:用于測試的新瀏覽器頁面(browser page)
會話作用域:這些 fixture 在測試函數請求時創建,在測試結束時銷毀。
- – playwright:Playwright 實例
- – browser_type:當前瀏覽器的 BrowserType 實例
- – browser:Playwright 啟動的 Browser 實例
- – browser_name:瀏覽器名稱
- – browser_channel:瀏覽器通道(channel)
- – is_chromium、is_webkit、is_firefox:各自瀏覽器類型的布爾值
自定義 fixture 選項:對于 browser 和 context fixture,使用下面的 fixture 定義自定義啟動選項。
- – browser_type_launch_args:重寫用于 browser_type.launch(**kwargs) 的啟動參數。它應該返回字典
- – browser_context_args:重寫用于 browser.new_context(**kwargs) 的選項。它應該返回字典
7.4. 并行:同時運行多個測試
如果測試運行在有許多 CPU 的機器上,可以通過使用 pytest-xdist 同時運行多個測試,加快測試套件的整體執行時間。
# install dependency
pip install pytest-xdist
# use the –numprocesses flag
pytest –numprocesses auto
根據硬件和測試的特性,可以將 numprocesses 設置為 2 到機器上 CPU 數量之間的任意值。如果設置得過高,可能產生非預期行為。
有關 pytest 選項的常用信息,請參考 Running Tests。
7.5. 示例
配置 Mypy 類型以自動補全
# test_my_application.py
from playwright.sync_api import Page
def test_visit_admin_dashboard(page: Page):
page.goto(“/admin”)
# …
配置慢動作
使用 –slowmo 參數以慢動作運行測試。
pytest –slowmo 100
通過瀏覽器跳過測試
# test_my_application.py
import pytest
@pytest.mark.skip_browser(“firefox”)
def test_visit_example(page):
page.goto(“Example Domain”)
# …
在特定的瀏覽器上運行測試
# conftest.py
import pytest
@pytest.mark.only_browser(“chromium”)
def test_visit_example(page):
page.goto(“Example Domain”)
# …
使用自定義的瀏覽器通道運行
pytest –browser-channel chrome
# test_my_application.py
def test_example(page):
page.goto(“Example Domain”)
配置 base-url
使用 base-url 參數啟動 Pytest。pytest-base-url 插件允許你通過配置、CLI 參數或像 fixture 一樣設置 base url。
pytest –base-url http://localhost:8080
# test_my_application.py
def test_visit_example(page):
page.goto(“/admin”)
# -> Will result in http://localhost:8080/admin
忽略 HTTPS 錯誤
# conftest.py
import pytest
@pytest.fixture(scope=”session”)
def browser_context_args(browser_context_args):
return {
**browser_context_args,
“ignore_https_errors”: True
}
使用自定義窗口大小
# conftest.py
import pytest
@pytest.fixture(scope=”session”)
def browser_context_args(browser_context_args):
return {
**browser_context_args,
“viewport”: {
“width”: 1920,
“height”: 1080,
}
}
設備仿真
# conftest.py
import pytest
@pytest.fixture(scope=”session”)
def browser_context_args(browser_context_args, playwright):
iphone_11 = playwright.devices[‘iPhone 11 Pro’]
return {
**browser_context_args,
**iphone_11,
}
或通過命令行
–device=”iPhone 11 Pro”。
持久化上下文
# conftest.py
import pytest
from playwright.sync_api import BrowserType
from typing import Dict
@pytest.fixture(scope=”session”)
def context(
browser_type: BrowserType,
browser_type_launch_args: Dict,
browser_context_args: Dict
):
context = browser_type.launch_persistent_context(“./foobar”, **{
**browser_type_launch_args,
**browser_context_args,
“locale”: “de-DE”,
})
yield context
context.close()
從持久化上下文創建測試內部的所有頁面。
與 unittest.TestCase 一起使用
參考下面的示例,了解如何與 unittest.TestCase 一起使用。這有一個限制,即只能指定一個瀏覽器,并且在指定多個瀏覽器時不會生成多個瀏覽器的矩陣。
import pytest
import unittest
from playwright.sync_api import Page
class MyTest(unittest.TestCase):
@pytest.fixture(autouse=True)
def setup(self, page: Page):
self.page = page
def test_foobar(self):
self.page.goto(“https://microsoft.com”)
self.page.locator(“#foobar”).click()
assert self.page.evaluate(“1 + 1”) == 2
7.6. 調試
在代碼中使用 breakpoint() 語句停止執行,獲取 pdb REPL。
def test_bing_is_working(page):
page.goto(“https://bing.com”)
breakpoint()
# …
7.7. 部署到 CI
請查看 guides for CI providers 獲取關于將測試部署到 CI/CD 的信息。
8. 認證
Playwright 可用于需要認證的自動化場景。
用 Playwright 編寫的測試在被稱為瀏覽器上下文(browser contexts)的獨立的干凈的環境中執行。這種隔離模型可以提升復現性,防止級聯測試失敗。新瀏覽器上下文可以加載現有的認證狀態。這可以消除在每個上下文中登錄的需求,加快測試執行的速度。
注意:本指南覆蓋 cookie/token-based 認證(通過 app UI 登陸)。對于 HTTP 認證(HTTP authentication),請使用 browser.new_context(**kwargs)。
8.1. 自動化登錄
Playwright API 可以與登陸表單自動化交互(automate interaction)。
下面的例子自動化登陸到 Github。執行這些步驟之后,瀏覽器上下文將被認證。
page = context.new_page()
page.goto(‘https://github.com/login’)
# Interact with login form
page.get_by_text(“Login”).click()
page.get_by_label(“User Name”).fill(USERNAME)
page.get_by_label(“Password”).fill(PASSWORD)
page.get_by_text(‘Submit’).click()
# Continue with the test
為每次測試重做登錄會減慢測試的執行速度。為緩解這種情況,應該重用現有的認證狀態。
8.2. 重用簽入狀態
Playwright 提供在測試中重用簽入(signed-in)狀態的方式。通過該方式,可以只登陸一次,然后跳過所有測試的登陸步驟。
Web 應用使用基于 Cookie 或基于 Token 的認證,認證狀態被當作 cookies 存儲,或存儲在 local storage 中。Playwright 提供 browserContext.storageState(options) 方法,可使用它從已認證上下文中獲取存儲狀態,然后使用預填充狀態創建新上下文。
Cookie 和 Local Storage 狀態可以跨不同的瀏覽器使用。它們依賴應用程序的認證模型:有些應用程序可能同時需要 Cookie 和 Local Storage。
下面的代碼片段從已認證上下文中獲取狀態,然后使用該狀態創建新上下文。
# Save storage state into the file.
storage = context.storage_state(path=”state.json”)
# Create a new context with the saved storage state.
context = browser.new_context(storage_state=”state.json”)
8.3. Session Storage
session storage 很少用于存儲與登陸狀態相關的信息。Session Storage 特定于特定的域,頁面加載時它不會持久化。Playwright 沒提供用于持久化 Session Storage 的 API,但下面的片段可用于保存/加載 Session Storage。
import os
# Get session storage and store as env variable
session_storage = page.evaluate(“() => JSON.stringify(sessionStorage)”)
os.environ[“SESSION_STORAGE”] = session_storage
# Set session storage in a new context
session_storage = os.environ[“SESSION_STORAGE”]
context.add_init_script(“””(storage => {
if (window.location.hostname === ‘Example Domain’) {
const entries = JSON.parse(storage)
for (const [key, value] of Object.entries(entries)) {
window.sessionStorage.setItem(key, key)
}
}
})(‘””” + session_storage + “‘)”)
8.4. 多因子認證
使用多因子認證(MFA)的賬戶無法完全自動化,需要人工干預。持久化認證可用于部分自動化 MFA 場景。
8.4.1 持久化認證
注意持久化認證不適用于 CI 環境,因為它依賴磁盤位置。用戶數據目錄特定于瀏覽器類型,不能跨瀏覽器類型共享。
用戶數據目錄可以與 browser_type.launch_persistent_context(user_data_dir, **kwargs) API 一起使用。
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
user_data_dir = ‘/path/to/directory’
browser = p.chromium.launch_persistent_context(user_data_dir, headless=False)
# Execute login steps manually in the browser window
生命周期
1. 在磁盤上創建用戶數據目錄
2. 使用用戶數據目錄啟動持久化上下文,然后登陸 MFA 賬戶
3. 重用用戶數據目錄來運行自動化場景
9. 事件
Playwright 允許監聽發生在 Web 頁面上的多種類型的事件,比如網絡請求、子頁面的創建、專用 Worker 等。可以通過多種方式訂閱這些事件,比如等待事件或添加/移除事件監聽者。
9.1. 等待事件
大多數時間,腳本需要等待特定的事件發生。下面是一些典型的事件等待模式。
使用 page.expect_request(url_or_predicate, **kwargs) 等待擁有指定 URL 的請求:
with page.expect_request(“**/*logo*.png”) as first:
page.goto(“https://wikipedia.org”)
print(first.value.url)
等待彈出窗口:
with page.expect_popup() as popup:
page.evaluate(“window.open()”)
popup.value.goto(“https://wikipedia.org”)
9.2. 添加/移除事件監聽者
有時,事件發生在隨機的事件,而不是等待它們,需要處理它們。Playwright 支持訂閱/取消訂閱事件的傳統語言機制:
def print_request_sent(request):
print(“Request sent: ” + request.url)
def print_request_finished(request):
print(“Request finished: ” + request.url)
page.on(“request”, print_request_sent)
page.on(“requestfinished”, print_request_finished)
page.goto(“https://wikipedia.org”)
page.remove_listener(“requestfinished”, print_request_finished)
page.goto(“https://www.openstreetmap.org/”)
9.3. 添加一次性監聽者
如果特定事件需要被處理一次,那么可以使用便捷的 API:
page.once(“dialog”, lambda dialog: dialog.accept(“2021”))
中國網絡空間安全協會
中國網絡空間安全協會
虹科網絡安全
安恒信息
一顆小胡椒
公安部網安局
奇安信集團
聚銘網絡
奇安信集團
聚銘網絡
一顆小胡椒
LemonSec