更新了框架中对于日志的处理逻辑
兼容 Python 脚本编写 和 YAML 数据驱动 两种模式的自动化测试框架,支持 Allure 和 Pure 两种测试报告。
-r
loguru
never
fail_only
always
page
allure.step
pure.step
automation_framework/ ├── config/ # 配置目录 │ ├── __init__.py │ └── settings.py # 全局配置文件 ├── tests/ # 测试用例目录 │ ├── __init__.py │ ├── conftest.py # Pytest 配置和 Fixtures(浏览器、登录会话等) ├── testcases/ # YAML 用例目录 ├── utils/ # 工具类目录 │ ├── __init__.py │ ├── log_tools.py # 日志初始化(loguru 配置) │ ├── yaml_engine.py # YAML 引擎 │ └── auth_session.py # 认证会话管理 ├── lib/ # 内置第三方库 │ ├── allure-2.22.0/ # Allure 命令行工具 │ └── pytest-pure-report/ # Pure 报告插件(自研) │ └── src/pytest_pure_report/ ├── outputs/ # 输出目录(运行后自动生成) │ ├── logs/ # 运行日志(每次运行一个独立日志文件) │ ├── pure_reports/ # Pure 报告根目录 │ └── allure_reports/ # Allure 报告根目录 ├── run.py # 测试运行入口 ├── pytest.ini # pytest 配置 ├── requirements.txt # Python 依赖 ├── Dockerfile # Docker 镜像配置 └── README.md # 项目说明
REPORT_TYPE
REPORT_TITLE
REPORT_ENV
REPORT_FILENAME
PURE_REPORTS_ROOT
ALLURE_REPORTS_ROOT
ALLURE_BIN
SCREENSHOT_SCOPE
VIDEO_SCOPE
BROWSER_TYPE
HEADLESS
BROWSER_WIDTH
BROWSER_HEIGHT
BROWSER_TIMEOUT
BASE_URL
TEST_USER_USERNAME
TEST_USER_PASSWORD
TEST_USER_DISPLAY_NAME
OUTPUTS_DIR
LOG_PATH
CASES_DIR
AUTH_DIR
框架支持两种 Allure 路径配置方式:
ALLURE_HOME
lib/allure-2.22.0/bin/
# 方式1: 设置环境变量(Windows) set ALLURE_HOME=C:\allure-2.22.0 # 方式2: 使用项目内置 Allure(无需配置) python run.py
截图/录屏配置的读取优先级(从高到低):
命令行参数 > settings.py 默认值 ↓ run.py 合并后注入环境变量 ↓ conftest.py / plugin.py 读取环境变量
截图与录屏的差异:
框架使用 loguru 作为日志库,采用 “初始化模块 + 直接调用” 设计:
from loguru import logger
logger.info()
logger.error()
logger.debug()
初始化触发方式:
在测试文件或工具模块中 import utils.log_tools(加 # noqa: F401 标注),执行模块顶层代码触发 loguru 配置。loguru 的 logger 是全局单例,初始化一次后所有模块共享配置。
import utils.log_tools
# noqa: F401
logger
from loguru import logger import utils.log_tools # noqa: F401 - 触发 loguru 初始化 logger.info("消息") # 同时输出到控制台和日志文件 logger.debug("调试信息") # 仅写入日志文件(控制台 level=INFO) logger.error("错误") # 同时输出到控制台和日志文件
日志文件位置:
outputs/logs/run_YYYYMMDD_HHMMSS.log
RUN_LOG_FILE
run_20260911_104557.log
pytest
为什么不用 log_info 封装函数?
log_info
原设计在 log_tools.py 中提供 log_info(msg) / log_error(msg) 封装函数,但存在以下问题:
log_tools.py
log_info(msg)
log_error(msg)
info
error
debug
warning
exception
框架对截图和录屏采用不同的触发机制,配置范围也有所不同:
截图在测试结束后通过 pytest_runtest_makereport hook 触发,此时测试结果(通过/失败)已知,可以按结果决定是否截图。
pytest_runtest_makereport
录屏在浏览器 context 创建时配置(Playwright API 限制),测试执行前就必须决定是否开启,无法提前预知测试结果。
为何录屏不支持 fail_only? Playwright 的录屏通过 record_video_dir 在 browser.new_context() 时配置,必须测试前就决定是否开启。测试执行时才能知道结果,但录屏早已启动,无法回溯关闭。 如需失败证据,请使用 SCREENSHOT_SCOPE=fail_only,截图在测试后触发,可按结果决定。
record_video_dir
browser.new_context()
SCREENSHOT_SCOPE=fail_only
方式1:修改 settings.py 默认值
# config/settings.py SCREENSHOT_SCOPE = "fail_only" # never / fail_only / always VIDEO_SCOPE = "never" # never / always
方式2:命令行参数覆盖(优先级更高)
# 仅失败时截图,不录屏 python run.py --screenshot fail_only --video-scope never # 全量截图录屏(调试用) python run.py --screenshot always --video-scope always # 不截图不录屏(最快) python run.py --screenshot never --video-scope never
在 tests/ 下新建文件,直接使用 Playwright 的 page 对象。 配合 allure.step 和 loguru 记录测试步骤和日志。
tests/
import pytest import allure from loguru import logger from pytest_pure_report import pure from config.settings import BASE_URL, TEST_USER_USERNAME, TEST_USER_PASSWORD import utils.log_tools # noqa: F401 - 触发 loguru 初始化(配置控制台/文件处理器) @allure.feature("用户登录") class TestLoginScript: @allure.story("登录成功") def test_login_success(self, page): """测试登录成功场景""" with allure.step(f"打开登录页面:{BASE_URL}/login"): logger.info(f"打开登录页面: {BASE_URL}/login") page.goto(f"{BASE_URL}/login", wait_until="networkidle") with allure.step("输入用户名和密码"): logger.info(f"输入用户名: {TEST_USER_USERNAME}") page.fill('input[placeholder="请输入手机号/用户名"]', TEST_USER_USERNAME) page.fill('input[placeholder="请输入登录密码"]', TEST_USER_PASSWORD) with allure.step("点击登录按钮"): logger.info("点击登录按钮") page.click("button:has-text('登 录')") with allure.step("验证登录成功"): page.wait_for_selector(".currentImg", timeout=10000)
框架提供认证会话管理功能,可以在测试间复用登录状态:
def test_with_auth(page, auth_session): # 应用已保存的会话(自动登录) auth_session.apply_session(page.context) # 访问需要登录的页面 page.goto("/dashboard") assert page.locator(".user-info").is_visible()
在 testcases/ 目录下新建 .yaml 文件,格式如下:
testcases/
name: "测试用例名称" steps: - action: "goto" # 关键字 desc: "步骤描述" # 报告中显示的步骤名 url: "https://..." # 参数
goto
url
fill
locator
text
click
type
delay
hover
dblclick
press
key
select_option
value
assert_visible
wait_for_selector
timeout
wait_for_url
screenshot
path
name: "用户登录测试" steps: - action: "goto" desc: "打开登录页面" url: "http://172.20.32.203:4000/login" - action: "fill" desc: "输入用户名" locator: "input[id='login_username']" text: "floraachy" - action: "fill" desc: "输入密码" locator: "input[id='login_password']" text: "12345678" - action: "click" desc: "点击登录按钮" locator: "button:has-text('登 录')" - action: "wait_for_selector" desc: "等待头像元素出现" locator: ".currentImg" timeout: 5000 - action: "assert_visible" desc: "验证登录成功" locator: ".currentImg"
创建虚拟环境:
python -m venv venv source venv/bin/activate # Linux/Mac venv\Scripts\activate # Windows
安装依赖:
pip install -r requirements.txt playwright install
# 默认运行(按 settings.py 配置的 REPORT_TYPE 生成报告) python run.py # 指定 Pure 报告 python run.py -r pure # 指定 Allure 报告 + 无头模式 + 过滤 login 关键词 python run.py -r allure --headless true -k login
-r, --report-type
python run.py -r pure
-b, --browser-type
python run.py -b firefox
--headless
python run.py --headless false
-k, --keyword
python run.py -k login
--screenshot
python run.py --screenshot always
--video-scope
python run.py --video-scope always
使用示例:
# Pure 报告 + 无头模式 + 不截图不录屏(快速验证) python run.py -r pure --headless true --screenshot never --video-scope never # Allure 报告 + Firefox 浏览器 + 过滤 login 关键词 python run.py -r allure -b firefox -k login # 全量截图录屏(调试时) python run.py -r pure --screenshot always --video-scope always
构建镜像:
docker build -t test-frame .
运行容器(结果挂载到本地):
docker run -v $(pwd)/outputs:/app/outputs test-frame
运行结束后,进入 outputs/pure_reports/<时间戳>/ 目录,直接用浏览器打开其中的 .html 文件即可查看报告(单文件,离线可看)。
outputs/pure_reports/<时间戳>/
.html
运行结束后,进入 outputs/allure_reports/<时间戳>/allure_report/ 目录,打开 index.html 查看报告。
outputs/allure_reports/<时间戳>/allure_report/
index.html
或使用 Allure 命令行启动本地服务:
allure serve outputs/allure_reports/<时间戳>/allure_results
Pure 报告是框架自研的 HTML 单文件报告,主要特性:
pure.step()
Pure 报告完全参考 allure 的 API 设计,业务侧代码无需修改即可在 Pure 报告模式下工作(框架已通过 patch_allure() 自动委托)。
allure
patch_allure()
from pytest_pure_report import pure # 上下文管理器(自动捕获异常状态:passed/failed/broken) with pure.step("打开登录页面"): page.goto("/login") # 装饰器(自动提取函数参数作为步骤参数展示) @pure.step("输入用户名和密码") def fill_credentials(page, username, password): page.fill("#username", username) page.fill("#password", password)
# 文本附件 pure.attach("hello world", name="问候", attachment_type=pure.attachment_type.TEXT) # 文件附件(如截图) pure.attach.file("screenshots/login.png", name="登录截图")
与原生 assert 配合,在报告中展示断言的预期值/实际值对比:
assert
assert page.title() == "GitLink" pure.record_equal(page.title(), "GitLink", "验证页面标题") pure.record_contains(resp.text, "success", "验证响应包含 success") pure.record_visible(page.locator(".avatar").is_visible(), "验证用户头像可见")
@pure.feature("登录") @pure.story("成功登录") @pure.severity(pure.severity_level.CRITICAL) @pure.tag("smoke") @pure.title("验证用户使用正确账号可以登录") def test_login_success(page): ...
def test_something(page): pure.dynamic.title("动态标题") pure.dynamic.tag("dynamic-tag") pure.dynamic.severity(pure.severity_level.BLOCKER)
pure.step(title)
pure.fixture(name)
pure.attach(body, ...)
pure.attach.file(source, ...)
pure.record(...)
pure.record_equal(...)
pure.record_contains(...)
pure.record_visible(...)
pure.title/description/feature/story/...
pure.dynamic
pure.severity_level
pure.attachment_type
# 使用 run.py 运行(推荐,自动生成报告) python run.py -r pure -k login # 直接使用 pytest 运行(调试时,不生成 Pure 报告) pytest tests/ -v -s # 运行特定测试 pytest tests/auth/test_login.py::TestLoginScript::test_login_success -v # 运行特定模块 pytest tests/projects/ -v
兼容 Python 脚本编写 和 YAML 数据驱动 两种模式的自动化测试框架。
版权所有:中国计算机学会技术支持:开源发展技术委员会 京ICP备13000930号-9 京公网安备 11010802047560号
混合驱动自动化测试框架
兼容 Python 脚本编写 和 YAML 数据驱动 两种模式的自动化测试框架,支持 Allure 和 Pure 两种测试报告。
核心特性
-r参数切换loguru记录运行日志,Pure 报告自动收集 setup/call/teardown 三阶段日志并合并展示never/fail_only/always),在测试结束后通过 hook 触发,可按结果决定never/always),在 context 创建时配置(Playwright 限制,无法按结果决定)page对象,配合allure.step或pure.step记录步骤框架目录结构
配置文件说明
config/settings.py
REPORT_TYPEREPORT_TITLEREPORT_ENVREPORT_FILENAMEPURE_REPORTS_ROOTALLURE_REPORTS_ROOTALLURE_BINSCREENSHOT_SCOPEVIDEO_SCOPEBROWSER_TYPEHEADLESSBROWSER_WIDTHBROWSER_HEIGHTBROWSER_TIMEOUTBASE_URLTEST_USER_USERNAMETEST_USER_PASSWORDTEST_USER_DISPLAY_NAMEOUTPUTS_DIRLOG_PATHCASES_DIRAUTH_DIRAllure 路径配置
框架支持两种 Allure 路径配置方式:
ALLURE_HOME指向 Allure 安装目录lib/allure-2.22.0/bin/下的 Allure配置数据流
截图/录屏配置的读取优先级(从高到低):
截图与录屏的差异:
fail_only模式fail_only模式日志配置
框架使用 loguru 作为日志库,采用 “初始化模块 + 直接调用” 设计:
from loguru import logger,使用logger.info()/logger.error()/logger.debug()初始化触发方式:
在测试文件或工具模块中
import utils.log_tools(加# noqa: F401标注),执行模块顶层代码触发 loguru 配置。loguru 的logger是全局单例,初始化一次后所有模块共享配置。日志文件位置:
outputs/logs/run_YYYYMMDD_HHMMSS.log(每次运行独立文件,不覆盖)RUN_LOG_FILE注入(如run_20260911_104557.log)pytest(不经 run.py)时,使用当前时间戳自动生成文件名为什么不用
log_info封装函数?原设计在
log_tools.py中提供log_info(msg)/log_error(msg)封装函数,但存在以下问题:logger本身就是全局单例,封装只是增加一层跳转,无附加价值info/error,debug/warning/exception都用不了from loguru import logger,直接使用更清晰截图与录屏配置
框架对截图和录屏采用不同的触发机制,配置范围也有所不同:
截图(SCREENSHOT_SCOPE)
截图在测试结束后通过
pytest_runtest_makereporthook 触发,此时测试结果(通过/失败)已知,可以按结果决定是否截图。neverfail_onlyalways录屏(VIDEO_SCOPE)
录屏在浏览器 context 创建时配置(Playwright API 限制),测试执行前就必须决定是否开启,无法提前预知测试结果。
neveralways配置方式
方式1:修改 settings.py 默认值
方式2:命令行参数覆盖(优先级更高)
如何编写测试用例
模式一:Python 脚本模式(推荐用于复杂逻辑)
在
tests/下新建文件,直接使用 Playwright 的page对象。 配合allure.step和loguru记录测试步骤和日志。使用认证会话管理
框架提供认证会话管理功能,可以在测试间复用登录状态:
模式二:YAML 模式(推荐用于简单流程)
在
testcases/目录下新建 .yaml 文件,格式如下:支持的关键字详解
gotourlfilllocator,textclicklocatortypelocator,textdelay(每个字符间隔毫秒)hoverlocatordblclicklocatorpresslocator,keyselect_optionlocator,valueassert_visiblelocatorwait_for_selectorlocatortimeout(毫秒,默认 10000)wait_for_urlurltimeout(毫秒,默认 10000)screenshotpath使用示例
快速开始
1. 环境准备
创建虚拟环境:
安装依赖:
2. 运行测试
命令行参数
-r, --report-typepython run.py -r pure-b, --browser-typepython run.py -b firefox--headlesspython run.py --headless false-k, --keywordpython run.py -k login--screenshotpython run.py --screenshot always--video-scopepython run.py --video-scope always使用示例:
3. Docker 运行
构建镜像:
运行容器(结果挂载到本地):
报告查看
Pure 报告
运行结束后,进入
outputs/pure_reports/<时间戳>/目录,直接用浏览器打开其中的.html文件即可查看报告(单文件,离线可看)。Allure 报告
运行结束后,进入
outputs/allure_reports/<时间戳>/allure_report/目录,打开index.html查看报告。或使用 Allure 命令行启动本地服务:
Pure 报告特性
Pure 报告是框架自研的 HTML 单文件报告,主要特性:
pure.step()添加自定义步骤、附件等Pure 报告 API
Pure 报告完全参考
allure的 API 设计,业务侧代码无需修改即可在 Pure 报告模式下工作(框架已通过patch_allure()自动委托)。步骤(上下文管理器 / 装饰器)
附件
断言记录(Pure 扩展,allure 无此功能)
与原生
assert配合,在报告中展示断言的预期值/实际值对比:标签装饰器(与 allure 完全一致)
运行时动态信息
API 一览
pure.step(title)pure.fixture(name)pure.attach(body, ...)pure.attach.file(source, ...)pure.record(...)pure.record_equal(...)pure.record_contains(...)pure.record_visible(...)pure.title/description/feature/story/...pure.dynamicpure.severity_levelpure.attachment_type常用命令