在 Web 自动化测试中,身份认证(如登录、Token 验证)是高频且关键的环节。重复执行登录操作不仅降低测试效率,还可能因状态残留导致测试失败。Playwright 通过灵活的浏览器上下文(Browser Context)管理和状态持久化机制,提供了高效的身份认证解决方案。
Playwright 身份认证的核心原理
浏览器上下文(Browser Context)
Playwright 在隔离的浏览器上下文中执行测试,每个上下文包含独立的 Cookie、LocalStorage 和 Session Storage,确保测试间的独立性。通过复用已认证的上下文状态,可避免重复登录。
认证状态存储
Playwright 支持将认证状态持久化为文件(如 JSON),存储以下内容:
- Cookies:跨会话的持久化认证标识
- LocalStorage:应用本地存储的 Token 或用户数据
- Session Storage(需特殊处理):会话级临时存储
推荐将状态文件保存在 playwright/.auth
目录并添加到 .gitignore
,防止敏感信息泄露。
基础方法:复用认证状态
使用 storage_state
持久化状态
通过 browser_context.storage_state()
方法保存认证状态,并在新上下文中加载:
# 同步模式示例
from playwright.sync_api import sync_playwright
def test_authenticated_flow():
with sync_playwright() as p:
browser = p.chromium.launch()
# 创建已认证的上下文
auth_context = browser.new_context()
auth_page = auth_context.new_page()
auth_page.goto("https://example.com/login")
# 执行登录操作...
# 保存状态到文件
auth_context.storage_state(path="auth_state.json")
# 创建新上下文并加载状态
new_context = browser.new_context(storage_state="auth_state.json")
new_page = new_context.new_page()
new_page.goto("https://example.com/dashboard")
# 验证认证状态...
异步模式实现
异步代码适用于高并发场景,需结合 async/await
语法:
# 异步模式示例
import asyncio
from playwright.async_api import async_playwright
async def async_auth():
async with async_playwright() as p:
browser = await p.chromium.launch()
auth_context = await browser.new_context()
auth_page = await auth_context.new_page()
await auth_page.goto("https://example.com/login")
# 异步登录操作...
await auth_context.storage_state(path="async_auth_state.json")
new_context = await browser.new_context(storage_state="async_auth_state.json")
new_page = await new_context.new_page()
await new_page.goto("https://example.com/dashboard")
Session Storage 与动态注入
某些应用使用 Session Storage 存储临时 Token,但 Playwright 默认不持久化该状态。需通过 JavaScript 手动保存和注入:
保存 Session Storage
def save_session_storage(page):
session_data = page.evaluate("() => JSON.stringify(sessionStorage)")
with open("session_storage.json", "w") as f:
f.write(session_data)
加载 Session Storage
def load_session_storage(context, hostname):
with open("session_storage.json", "r") as f:
session_data = f.read()
context.add_init_script(f"""
(storage => {
{
if (window.location.hostname === '{
hostname}') {
{
const entries = JSON.parse(storage);
Object.entries(entries).forEach(([key, value]) => {
{
window.sessionStorage.setItem(key, value);
}});
}}
}})('{
session_data}')
""")
自动化登录与脚本录制
4使用 playwright codegen
录制登录流程
通过命令行工具自动生成登录脚本并保存认证状态:
# 录制并保存认证状态
playwright codegen --save-storage=auth.json https://example.com/login
# 复用认证状态启动浏览器
playwright open --load-storage=auth.json https://example.com/dashboard
集成到测试框架(Pytest)
通过 Fixture 实现全局认证状态管理:
# conftest.py
import pytest
from playwright.sync_api import Page, BrowserContext
@pytest.fixture(scope="session")
def auth_context(browser: BrowserContext):
context = browser.new_context()
page = context.new_page()
page.goto("https://example.com/login")
page.fill("#username", "[email protected]")
page.fill("#password", "password123")
page.click("#submit")
context.storage_state(path="auth_state.json")
yield context
context.close()
@pytest.fixture
def authenticated_page(auth_context):
return auth_context.new_page()