Python + Pytest + Allure + Playwright 自动化测试框架搭建教程
本文详细介绍如何搭建一个企业级的自动化测试框架,包含 Python + Pytest + Allure + Playwright。
一、技术栈介绍
1.1 各技术简介
| 技术 |
作用 |
特点 |
| Python |
编程语言 |
简单易学、生态丰富 |
| Pytest |
测试框架 |
简洁强大、插件丰富 |
| Allure |
测试报告 |
美观直观、支持历史趋势 |
| Playwright |
自动化工具 |
跨浏览器、自动等待 |
1.2 框架架构
自动化测试框架/
├── core/ # 核心模块
│ ├── base.py # 基类封装
│ ├── driver.py # 浏览器驱动
│ └── logger.py # 日志管理
├── pages/ # 页面对象
│ ├── base_page.py # 页面基类
│ └── demo_page.py # 具体页面
├── testcases/ # 测试用例
│ ├── test_login.py
│ └── test_search.py
├── utils/ # 工具类
│ ├── config.py # 配置管理
│ └── excel_helper.py # 数据驱动
├── data/ # 测试数据
│ └── test_data.xlsx
├── reports/ # 测试报告
├── requirements.txt # 依赖
└── pytest.ini # 配置文件
二、环境准备
2.1 安装 Python
# 检查 Python 版本
python3 --version
# 建议使用 Python 3.8+
2.2 创建虚拟环境
# 创建项目目录
mkdir auto_framework && cd auto_framework
# 创建虚拟环境
python3 -m venv venv
# 激活虚拟环境
# Linux/Mac:
source venv/bin/activate
# Windows:
venv\Scripts\activate
2.3 安装依赖
pip install pytest playwright allure-pytest pytest-playwright
# 初始化 Playwright
playwright install chromium
三、核心配置
3.1 requirements.txt
pytest==7.4.3
playwright==1.40.0
allure-pytest==2.13.2
pytest-html==4.1.1
pytest-xdist==3.5.0
pytest-repeat==0.9.3
python-dotenv==1.0.0
openpyxl==3.1.2
loguru==0.7.2
3.2 pytest.ini
[pytest]
# 测试路径
testpaths = testcases
# 文件匹配
python_files = test_*.py
python_classes = Test*
python_functions = test_*
# 标记
markers =
smoke: 冒烟测试
regression: 回归测试
login: 登录相关
slow: 慢速测试
# 日志
log_cli = true
log_cli_level = INFO
log_cli_format = %(asctime)s [%(levelname)8s] %(message)s
log_cli_date_format = %Y-%m-%d %H:%M:%S
# 报告
addopts = -v --tb=short --html=reports/report.html --self-contained-html
3.3 .env 配置文件
# .env 文件
ENV=TEST
BASE_URL=https://demo.test.com
BROWSER=chromium
HEADLESS=true
TIMEOUT=30000
四、核心代码实现
4.1 浏览器驱动封装 (core/driver.py)
import os
from playwright.sync_api import sync_playwright
from dotenv import load_dotenv
load_dotenv()
class BrowserDriver:
"""浏览器驱动管理"""
@staticmethod
def get_browser():
"""获取浏览器实例"""
playwright = sync_playwright().start()
browser = playwright.chromium.launch(
headless=os.getenv("HEADLESS", "true").lower() == "true",
args=['--disable-blink-features=AutomationControlled']
)
return playwright, browser
@staticmethod
def get_context(browser):
"""获取浏览器上下文"""
context = browser.new_context(
viewport={'width': 1920, 'height': 1080},
locale='zh-CN'
)
return context
@staticmethod
def get_page(context):
"""获取新页面"""
page = context.new_page()
page.set_default_timeout(int(os.getenv("TIMEOUT", "30000")))
return page
4.2 页面基类 (pages/base_page.py)
from playwright.sync_api import Page
from loguru import logger
class BasePage:
"""页面对象基类"""
def __init__(self, page: Page):
self.page = page
def goto(self, url: str):
"""跳转URL"""
logger.info(f"打开页面: {url}")
self.page.goto(url)
def click(self, selector: str):
"""点击元素"""
logger.info(f"点击元素: {selector}")
self.page.click(selector)
def fill(self, selector: str, value: str):
"""输入文本"""
logger.info(f"输入内容到 {selector}: {value}")
self.page.fill(selector, value)
def get_text(self, selector: str) -> str:
"""获取文本"""
return self.page.text_content(selector)
def wait_for_selector(self, selector: str, timeout: int = 30000):
"""等待元素出现"""
self.page.wait_for_selector(selector, timeout=timeout)
def screenshot(self, name: str = "screenshot"):
"""截图"""
self.page.screenshot(path=f"reports/screenshots/{name}.png")
def is_visible(self, selector: str) -> bool:
"""检查元素是否可见"""
return self.page.is_visible(selector)
4.3 日志配置 (core/logger.py)
import sys
from loguru import logger
import os
# 移除默认处理器
logger.remove()
# 控制台输出
logger.add(
sys.stdout,
format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan> - <level>{message}</level>",
level="INFO"
)
# 文件输出
log_dir = "reports/logs"
os.makedirs(log_dir, exist_ok=True)
logger.add(
f"{log_dir}/{{time:YYYY-MM-DD}}.log",
rotation="00:00",
retention="30 days",
level="DEBUG",
format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function} - {message}"
)
五、测试用例示例
5.1 conftest.py ( fixtures )
import pytest
from playwright.sync_api import sync_playwright
from core.driver import BrowserDriver
from core.logger import logger
import os
@pytest.fixture(scope="session")
def browser():
"""浏览器 fixture"""
playwright, browser = BrowserDriver.get_browser()
yield browser
browser.close()
playwright.stop()
@pytest.fixture(scope="function")
def page(browser):
"""页面 fixture"""
context = browser.new_context(
viewport={'width': 1920, 'height': 1080}
)
page = context.new_page()
yield page
context.close()
@pytest.fixture(scope="function", autouse=True)
def test_info(request):
"""打印测试信息"""
logger.info(f"开始执行: {request.node.name}")
yield
logger.info(f"结束执行: {request.node.name}")
5.2 登录测试用例
import pytest
from pages.login_page import LoginPage
from pages.home_page import HomePage
from core.logger import logger
class TestLogin:
"""登录测试"""
@pytest.mark.login
def test_login_success(self, page):
"""测试登录成功"""
login_page = LoginPage(page)
home_page = HomePage(page)
# 执行登录
login_page.goto("https://demo.test.com/login")
login_page.login("testuser", "password123")
# 断言
assert home_page.is_logged_in(), "登录失败"
logger.info("登录成功 ✓")
@pytest.mark.login
def test_login_failed(self, page):
"""测试登录失败"""
login_page = LoginPage(page)
login_page.goto("https://demo.test.com/login")
login_page.login("wronguser", "wrongpass")
# 断言登录失败提示
assert login_page.get_error_msg() == "用户名或密码错误"
logger.info("登录失败用例通过 ✓")
六、Allure 报告配置
6.1 生成 Allure 报告
# 运行测试并生成 Allure 数据
pytest testcases/ --alluredir=reports/allure-results
# 生成 HTML 报告
allure serve reports/allure-results
6.2 添加测试描述
import allure
@allure.title("登录成功测试")
@allure.description("验证用户使用正确账号密码可以成功登录")
@allure.severity(allure.severity_level.BLOCKER)
@allure.feature("登录功能")
@allure.story("用户登录")
def test_login_success(page):
"""测试登录成功"""
pass
6.3 附件支持
def test_with_screenshot(page):
"""带截图的测试"""
page.goto("https://example.com")
# 添加截图
page.screenshot(path="screenshot.png")
allure.attach.file("screenshot.png", attachment_type=allure.attachment_type.PNG)
# 添加日志
allure.attach("这是测试日志", name="日志", attachment_type=allure.attachment_type.TEXT)
七、数据驱动测试
7.1 CSV 数据驱动
import pytest
import csv
@pytest.mark.parametrize("username,password,expected", [
("user1", "pass1", "success"),
("user2", "pass2", "fail"),
])
def test_login_data_driven(username, password, expected):
"""CSV数据驱动测试"""
print(f"Testing: {username} / {password}")
7.2 Excel 数据驱动
import openpyxl
def get_test_data():
"""从Excel读取测试数据"""
wb = openpyxl.load_workbook("data/test_data.xlsx")
ws = wb.active
data = []
for row in ws.iter_rows(min_row=2, values_only=True):
data.append(row)
return data
@pytest.mark.parametrize("username,password,expected", get_test_data())
def test_login_excel(username, password, expected):
"""Excel数据驱动"""
print(f"Testing: {username}")
八、CI/CD 集成
8.1 GitHub Actions
name: Auto Test
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install dependencies
run: |
pip install -r requirements.txt
playwright install chromium
- name: Run tests
run: pytest testcases/ --alluredir=reports/allure-results
- name: Upload Allure results
uses: actions/upload-artifact@v3
if: always()
with:
name: allure-results
path: reports/allure-results
8.2 Jenkinsfile
pipeline {
agent any
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Install') {
steps {
sh 'pip install -r requirements.txt'
sh 'playwright install chromium'
}
}
stage('Test') {
steps {
sh 'pytest testcases/ --alluredir=reports/allure-results'
}
}
stage('Report') {
steps {
allure includeProperties: false, results: [[path: 'reports/allure-results']], report: 'reports/allure-report'
}
}
}
}
九、常用命令汇总
9.1 测试运行命令
# 运行所有测试
pytest
# 运行指定文件
pytest testcases/test_login.py
# 运行指定标记
pytest -m smoke
# 跳过标记
pytest -m "not slow"
# 并行执行
pytest -n 4
# 失败重试
pytest --reruns 3
# 生成HTML报告
pytest --html=reports/report.html
# 生成Allure报告
pytest --alluredir=reports/allure-results
9.2 Allure 报告命令
# 生成报告
allure generate reports/allure-results -o reports/allure-report
# 打开报告
allure open reports/allure-report
# 启动服务
allure serve reports/allure-results
十、常见问题
Q1: Playwright 浏览器下载失败
解决:
playwright install chromium --with-deps
Q2: Allure 报告中文乱码
解决:
allure generate -c -Dallure.results.directory=reports/allure-results -Dallure.link.issue.pattern=https://jira.test.com/browse/{}
Q3: 元素找不到
解决: 使用自动等待
page.wait_for_load_state("networkidle")
page.click("selector", timeout=10000)
Q4: 截图保存失败
解决: 确保目录存在
os.makedirs("reports/screenshots", exist_ok=True)
十一、总结
本框架特点:
✅ 结构清晰 - Page Object 模式
✅ 易于维护 - 页面元素与逻辑分离
✅ 报告美观 - Allure 集成
✅ 数据驱动 - 支持 Excel/CSV
✅ CI/CD 集成 - 支持 GitHub Actions/Jenkins
✅ 日志完善 - 详细的执行日志
快去搭建你的自动化测试框架吧!
需要帮助随时问我!