基于 Playwright + Pytest + Allure 的 UI 自动化测试框架
Project description
pwtest
基于 Playwright + Pytest + Allure 的 UI 自动化测试框架
✨ 特性
- 🚀 开箱即用: 集成 Playwright、Pytest、Allure,无需复杂配置
- 🎯 POM 设计模式: 清晰的页面对象模型,易于维护
- 📊 美观的测试报告: 自动生成 Allure 报告,支持视频录制和截图
- 🔄 状态管理: 智能的浏览器状态管理,避免重复登录
- 🌐 多浏览器支持: 支持 Chromium、Firefox、WebKit、Chrome、Edge
- 📝 详细日志: 基于 loguru 的日志系统,方便调试
- ⚡ 并行测试: 支持多浏览器并行执行
- 🎨 灵活配置: 支持配置继承和覆盖
📦 安装
从 PyPI 安装(推荐)
pip install pwtest
从源码安装
git clone https://github.com/mofanx/pwtest.git
cd pwtest
pip install -e .
安装 Playwright 浏览器
# 安装框架后,需要安装 Playwright 浏览器
playwright install
# 或者只安装特定浏览器
playwright install chromium
🚀 快速开始
方式 1: 使用 CLI 初始化(推荐) ⭐
# 创建项目目录
mkdir my_test_project
cd my_test_project
# 使用 pwtest 命令初始化项目
pwtest init
# 完成! 所有必需的文件和目录都已创建
pwtest init 会自动创建:
- ✅ 目录结构 (config/, pages/, tests/)
- ✅ 配置文件 (pytest.ini, config/config.py)
- ✅ 测试配置 (conftest.py)
- ✅ 示例文件 (login_page.py, test_example.py)
- ✅ 项目文档 (README.md, .gitignore)
方式 2: 手动创建
如果你想手动创建项目结构:
mkdir my_test_project
cd my_test_project
mkdir -p config pages tests
2. 创建 pytest.ini (必需)
重要: 测试项目需要自己的 pytest.ini,框架内的配置不会自动生效。
# pytest.ini
[pytest]
minversion = 8.0
testpaths = tests
python_files = test_*.py
python_classes = Test*
python_functions = test_*
addopts = -v --tb=short --capture=no
markers =
smoke: 冒烟测试用例
regression: 回归测试用例
user: 需要全新浏览器实例的测试
3. 创建配置文件
# config/config.py
from pwtest import Config as BaseConfig
class Config(BaseConfig):
BASE_URL = "https://your-test-site.com"
VALID_USERNAME = "user"
VALID_PASSWORD = "password"
# 可选: 覆盖框架默认配置
HEADLESS = False
VIDEO_RECORD = True
settings = Config()
4. 创建 conftest.py (必需)
# conftest.py
from pwtest.conftest import * # 导入框架的所有 fixtures
from config.config import settings
# 定义 login_callback 以启用登录状态管理
@pytest.fixture(scope="session")
def login_callback():
"""提供登录回调函数
此 fixture 会被框架自动检测和使用。
如果不需要登录状态管理,可以不定义此 fixture。
"""
def do_login(page):
# 方式 1: 使用页面对象(推荐)
from pages.login_page import LoginPage
login_page = LoginPage(page)
login_page.login(settings.VALID_USERNAME, settings.VALID_PASSWORD)
# 方式 2: 直接操作(简单场景)
# page.goto("/login")
# page.fill("#username", settings.VALID_USERNAME)
# page.fill("#password", settings.VALID_PASSWORD)
# page.click("button[type='submit']")
return do_login
注意:
login_callback是可选的,只有需要登录状态管理时才定义- 框架会自动检测并使用此 fixture
- 如果不定义,每个测试需要自己处理登录
5. 创建页面对象
# pages/login_page.py
class LoginPage:
def __init__(self, page):
self.page = page
self.username_input = page.get_by_placeholder("请输入账号")
self.password_input = page.get_by_placeholder("请输入密码")
self.login_button = page.get_by_role("button", name="登录")
def login(self, username: str, password: str):
self.page.goto("/login")
self.username_input.fill(username)
self.password_input.fill(password)
self.login_button.click()
6. 编写测试用例
# tests/test_example.py
import allure
@allure.feature("登录功能")
@allure.story("用户登录")
def test_successful_login(page):
"""测试成功登录"""
page.goto("/dashboard")
expect(page).to_have_title("预期标题")
7. 运行测试
# 运行所有测试
pytest tests/ -v
# 运行指定浏览器
pytest tests/ --browsers=chromium
# 运行多个浏览器
pytest tests/ --browsers=chromium,firefox
# 生成 Allure 报告
pytest tests/ --alluredir=allure-results
allure serve allure-results
📖 详细文档
配置说明
框架提供了丰富的配置选项,可以通过继承 Config 类来覆盖默认配置:
from pwtest import Config as BaseConfig
class Config(BaseConfig):
# 基础配置
BASE_URL = "https://example.com"
# 浏览器配置
BROWSER_TYPE = "chromium" # chromium, firefox, webkit
HEADLESS = False
SLOW_MO = 100 # 操作间隔(毫秒)
# 超时配置
DEFAULT_TIMEOUT = 30000
NAVIGATION_TIMEOUT = 30000
# 视窗配置
VIEWPORT_WIDTH = 1920
VIEWPORT_HEIGHT = 1080
# 截图配置
SCREENSHOT_ON_FAILURE = True
SCREENSHOT_PATH = "screenshots"
# 视频录制配置
VIDEO_RECORD = True
VIDEO_PATH = "videos"
AUTO_CLEANUP_PASSED_VIDEOS = True
# 操作录制配置
TRACING_ON = False
TRACING_PATH = "tracings"
AUTO_CLEANUP_PASSED_TRACINGS = True
# 业务配置
VALID_USERNAME = "testuser"
VALID_PASSWORD = "password123"
STATE_PATH = "state.json"
settings = Config()
登录回调函数
框架使用 login_callback 机制实现登录逻辑的解耦:
@pytest.fixture(scope="session")
def login_callback():
"""提供登录回调函数"""
def do_login(page):
# 方式1: 使用页面对象
login_page = LoginPage(page)
login_page.login(username, password)
# 方式2: 直接操作
# page.goto("/login")
# page.fill("#username", username)
# page.fill("#password", password)
# page.click("button[type='submit']")
return do_login
多浏览器测试
# 单个浏览器
pytest --browsers=chromium
# 多个浏览器
pytest --browsers=chromium,firefox,webkit
# 所有浏览器
pytest --browsers=all
# 使用系统浏览器
pytest --browsers=chrome # 或 msedge
测试标记
框架预定义了常用的测试标记:
@pytest.mark.smoke
def test_critical_feature(page):
"""冒烟测试"""
pass
@pytest.mark.no_login
def test_login(page):
"""需要全新浏览器的测试"""
pass
@pytest.mark.regression
def test_all_features(page):
"""回归测试"""
pass
🎯 最佳实践
1. 使用页面对象模式
# pages/base_page.py
class BasePage:
def __init__(self, page):
self.page = page
def navigate_to(self, path):
self.page.goto(path)
# pages/login_page.py
class LoginPage(BasePage):
def login(self, username, password):
# 登录逻辑
pass
2. 使用 Allure 装饰器
import allure
from pages.login_page import LoginPage
@allure.feature("用户管理")
@allure.story("用户登录")
@allure.severity(allure.severity_level.CRITICAL)
def test_login(page):
login_page = LoginPage(page)
with allure.step("访问登录页"):
login_page.goto_login()
with allure.step("输入用户名和密码"):
login_page.input_username(settings.VALID_USERNAME)
login_page.input_password(settings.VALID_PASSWORD)
with allure.step("点击登录按钮"):
login_page.click_login_button()
3. 使用数据驱动测试
import pytest
@pytest.mark.parametrize("username,password,expected", [
("user1", "pass1", True),
("user2", "pass2", False),
])
def test_login_with_data(page, username, password, expected):
# 测试逻辑
pass
4. 环境变量管理
import os
class Config:
BASE_URL = os.getenv("TEST_BASE_URL", "https://default.com")
USERNAME = os.getenv("TEST_USERNAME", "default_user")
PASSWORD = os.getenv("TEST_PASSWORD", "default_pass")
🔧 高级功能
自定义 Fixture
# conftest.py
@pytest.fixture
def api_client():
"""API客户端fixture"""
return APIClient(base_url=settings.API_URL)
@pytest.fixture
def test_data():
"""测试数据fixture"""
return load_test_data("test_data.json")
覆盖框架 Fixture
# 覆盖context fixture
@pytest.fixture(scope="session")
def context(browser):
"""自定义context配置"""
context = browser.new_context(
viewport={"width": 1280, "height": 720},
# 自定义配置
)
yield context
context.close()
📊 测试报告
框架自动生成详细的测试报告:
- Allure 报告: 美观的 HTML 报告,包含测试步骤、截图、视频
- HTML 报告: pytest-html 生成的简单报告
- 日志文件: 详细的测试执行日志
临时查看 Allure 报告:
allure serve allure-results
生成 Allure 报告:
allure generate ./allure-results -o ./allure-report --clean --lang zh
allure open ./allure-report
🤝 贡献
欢迎提交 Issue 和 Pull Request!
📄 许可证
🔗 相关链接
🔧 CLI 命令
pwtest init
初始化测试项目,自动创建所有必需的文件和目录。
# 在当前目录初始化
pwtest init
# 在指定目录初始化
pwtest init --dir my_project
# 强制覆盖已存在的文件
pwtest init --force
pwtest --version
显示框架版本信息。
pwtest --version
📦 构建和发布
本地构建
# 安装构建工具
pip install build twine
# 构建包
python -m build
# 检查包
twine check dist/*
发布到 PyPI
# 发布到 TestPyPI (测试)
twine upload --repository testpypi dist/*
# 发布到 PyPI (正式)
twine upload dist/*
📮 联系方式
- GitHub: https://github.com/mofanx/pwtest
- 作者: mofanx
- Issues: https://github.com/mofanx/pwtest/issues
🙏 致谢
感谢以下开源项目:
- Playwright 文档 - 强大的浏览器自动化工具
- Pytest 文档 - 优秀的 Python 测试框架
- Allure 文档 - 美观的测试报告框架
pwtest - 让 UI 自动化测试更简单! 🚀
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pwtest-1.0.2.tar.gz.
File metadata
- Download URL: pwtest-1.0.2.tar.gz
- Upload date:
- Size: 27.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
548336049a415305e3f8d3610a9ff718a872fe67fb3ab4aa023e309953f2c12d
|
|
| MD5 |
d6d53d3f7898059cefc35af854e49232
|
|
| BLAKE2b-256 |
ee7a6b7ccb22712cfdc7aa65e3247bd238531fc68c6dbd81b1b675062f043e53
|
File details
Details for the file pwtest-1.0.2-py3-none-any.whl.
File metadata
- Download URL: pwtest-1.0.2-py3-none-any.whl
- Upload date:
- Size: 29.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
06d77b00e6ff9c938dc4f7800692577ef24ca3d1340001a6269cf1d27b8e1c08
|
|
| MD5 |
d9a0b3c8b60af0eddd555499f3b199fd
|
|
| BLAKE2b-256 |
5d1758dc8cf11f2e9ed8f2ecb85332100587c8663da3f37970bbd3269c5e641f
|