尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

从Pytest到Allure:Jenkins集成自动化测试报告实战指南

从Pytest到Allure:Jenkins集成自动化测试报告实战指南 先交代个背景。我自己维护的接口自动化用例从最早用 HTMLTestRunner 出报告到后来换成 pytest-html再到最后彻底切到 Allure中间经历过不止一次“报告没人看”的尴尬阶段。倒不是用例写得不好而是报告本身的信息组织方式没法让开发、测试、项目经理在五分钟内看懂“这轮构建到底挂了什么、挂在哪、影响面多大”。直到把 pytest Allure 跑通再挂到 Jenkins 上用 Allure 插件出报告这套链路才算真正稳定下来也才敢说“自动化结果能驱动决策了”。这篇东西不打算写成像官方文档那样的罗列而是把我在实际搭建过程中踩过的坑、验证过的配置、以及最后沉淀下来的一整套可复现的 Jenkins Allure 插件方案完整梳理出来。无论你是刚接触 pytest 的测试新人还是已经在用 pytest 但报告环节一直没理顺的资深测试这篇都能给你一条直接照着做的路径。1. 为什么最终选了 Allure从“报告没人看”到“报告能说话”先聊一个最现实的问题测试报告到底给谁看如果只是给自己看那 pytest 终端输出或者 pytest-html 生成的静态页面完全够用。但一旦用例规模上来涉及多个模块、多层接口依赖、失败用例需要追溯到具体请求参数和响应内容时报告的组织方式就直接决定了排障效率。我见过太多团队的报告是“一长串用例名 通过/失败标记”的平铺结构失败原因得点进堆栈里自己翻时间一长开发根本不愿意打开这种报告。Allure 解决的恰恰是这个问题。它把测试结果组织成“套件 - 特性 - 场景 - 步骤”的层级结构每个用例可以挂上严重级别、缺陷链接、关联需求、步骤日志、附件截图甚至在接口测试里直接展示请求报文和响应报文。Jenkins 上装了 Allure 插件之后每次构建结束会自动解析 allure-results 目录下的结果文件生成一份带趋势图、缺陷分类、历史对比的报告页面。报告不再是一个静态的“结果快照”而是能反映项目质量演进过程的“动态看板”。再说选型对比这可能是很多团队纠结的地方pytest-html轻量生成快适合用例量少、纯自用的场景。但它的报告是单页静态文件Jenkins 里虽然能直接打开但历史趋势、失败聚合这些能力基本没有用例一多页面就非常长查找信息效率低。HTMLTestRunnerunittest 时代的产物pytest 下用还要做适配维护状态基本停滞。Allure学习曲线最陡但收益也最明显。它有命令行工具负责生成报告有 pytest-allure-adapter 负责采集数据Jenkins 有官方插件负责集成生态完整且报告的美观度和信息密度在开源方案里是第一档。所以我的结论很直接如果你们团队的自动化用例会长期维护、需要多人协作看结果、或者有向管理层汇报质量数据的诉求直接上 Allure不要犹豫。它的学习成本主要集中在“如何组织用例描述”而不是“如何使用工具”而这部分投入是值得的。2. 环境准备最容易翻车的地方Java版本、命令行工具、依赖安装很多教程会直接说“pip install allure-pytest然后 brew install allure”但实际在公司内网机器或 Linux 服务器上搭环境时问题往往出在几个容易被忽略的细节上。2.1 Java 环境Allure 的命令行工具是 Java 写的Allure 2.x 的命令行工具依赖 Java 8 或更高版本。Jenkins 本身如果跑在 Java 11 上那 Allure 命令行用 Java 8 编译的版本也能跑但如果你同时装了多个 JDK一定要确认 PATH 里指向的 java 版本可用。我在 CentOS 7.9 上就踩过这个坑系统默认 java 是 1.7Allure 命令行怎么都起不来报的错还比较隐晦提示找不到主类。后来把 JAVA_HOME 指到 JDK 1.8 才正常。提示用java -version确认版本低于 1.8 必须升级。如果服务器上有多个 JDK建议在 /etc/profile 或 ~/.bashrc 里显式设置 JAVA_HOME避免 Allure 命令行和 Jenkins 用的是不同的 Java。2.2 Allure 命令行工具的两种安装方式直接下载压缩包推荐尤其是内网环境 从官方 GitHub Releases 页面下载 allure-commandline 的 zip 包解压后把 bin 目录加入 PATH。整个过程不依赖包管理器适合离线部署。通过包管理器安装 macOS 上brew install allureWindows 上可以用 scoop 或 choco。但公司内网 Linux 服务器通常没这些工具所以用得最多的还是直接下载压缩包。装完之后验证一下allure --version如果能正常输出版本号说明命令行工具没问题。2.3 pytest 侧的依赖需要装的是allure-pytest它是 pytest 和 Allure 之间的适配器负责把 pytest 的测试结果转换成 allure-results 目录下的 JSON 文件。和 pytest-html 那种直接生成 HTML 的方式不同Allure 的流程是“先生成原始结果文件再通过命令行工具渲染成 HTML 报告”。pip install allure-pytest安装完成后在 pytest.ini 里加上一行配置让 pytest 默认就带上 Allure 的插件[pytest] addopts -vs --alluredirallure-results这样每次跑 pytest 的时候会自动在 allure-results 目录下生成结果文件不需要手动在命令行里加参数。这个细节很实用尤其是后面接 Jenkins 时构建步骤只需要执行pytest一个命令避免参数漏传。3. Pytest 用例改造让 Allure 报告真正有信息量如果没有做任何用例改造直接用默认配置跑一遍Allure 报告生成出来其实只是“换了个皮肤的 pytest 结果列表”那还不如用 pytest-html。Allure 真正的威力在于它的注解体系和多级结构。这一节我会直接给出我平时最常用的一套改造模板。3.1 编写一个带完整 Allure 注解的用例示例下面这个示例是我在接口自动化项目里的一个真实用例简化版完整覆盖了 role、story、severity、step、attachment 这几个高频注解import allure import pytest import requests allure.epic(用户中心) allure.feature(登录模块) allure.story(密码登录) allure.severity(allure.severity_level.BLOCKER) class TestLogin: allure.title(密码登录成功场景) allure.link(https://jira.example.com/browse/LOGIN-101, name需求单) def test_login_success(self): with allure.step(构造请求数据): payload {username: testuser, password: 123456} headers {Content-Type: application/json} with allure.step(发送登录请求): response requests.post(https://api.example.com/login, jsonpayload, headersheaders) with allure.step(校验响应结果): assert response.status_code 200 assert response.json()[code] 0 allure.attach(response.text, 登录接口响应, allure.attachment_type.TEXT)这里每个注解解决一个问题allure.epic/allure.feature/allure.story定义层级关系。在报告首页左侧的“Behaviors”视图里用例会按这个三级结构折叠展示管理层看进度、测试看明细都很方便。allure.severity标记严重级别。如果用例里某些场景属于冒烟级别在 Jenkins 上可以单独筛出来跑报告里也能按严重级别过滤。allure.title给用例起一个“人话”标题。默认的标题是函数名snake_case 风格在报告里看起来非常费劲改成中文描述后报告的易读性直接上一个台阶。allure.step把用例拆成多个步骤。失败时报告里能直接看到“卡在哪个步骤”而不是给你一整个函数的 traceback 让你自己猜。allure.attach把关键数据附到报告里。对接口测试来说把响应报文附上去开发排查问题时连日志都不用翻。3.2 一个用例文件里要处理好的“描述粒度”问题我在实际项目中反复调整过注解的使用粒度最终沉淀出一个原则用例的函数名管“跑不跑得通”allure.title 管“别人看不看得懂”。每一条用例都值得写一个清晰的中文标题但 allure.step 不要滥用一个用例里 3~5 个步骤最合理太多反而让报告变得碎片化。另外allure.attach 的用法值得多说一句。除了直接 attach 文本还可以 attach JSON 结构import json allure.attach(json.dumps(response.json(), ensure_asciiFalse, indent2), 响应数据, allure.attachment_type.JSON)这样在报告里 JSON 会以格式化后的形式展示比纯文本更清晰。3.3 失败用例自动截图对于 UI 自动化是刚需如果你的 pytest 用例不只是接口测试还有 UI 自动化部分那失败自动截图基本上是必须的。我常用的做法是写一个 pytest 的 hook在用例失败后自动截取当前浏览器页面并附加到 Allure 报告里# conftest.py import allure import pytest pytest.hookimpl(hookwrapperTrue) def pytest_runtest_makereport(item, call): outcome yield report outcome.get_result() if report.when call and report.failed: driver item.funcargs.get(driver) if driver: allure.attach(driver.get_screenshot_as_png(), 失败截图, allure.attachment_type.PNG)这样用例失败时报告里除了堆栈信息还会有一张当时的页面截图排障效率高非常多。4. Jenkins 侧的完整落地插件安装、全局工具配置、构建步骤环境准备和用例改造都做完之后就到了“把流程固化到 Jenkins 上”的环节。这一步踩的坑主要集中在插件版本兼容、全局工具配置路径、以及构建后操作的参数设置上。4.1 安装 Allure 插件和 JDK 插件在 Jenkins 的“系统管理 → 插件管理 → 可选插件”里搜索 Allure安装Allure Jenkins Plugin。这个插件的作用是让 Jenkins 识别 allure 命令行工具同时提供“构建后操作”里生成报告的能力。另外如果你的 Jenkins 服务器和运行 pytest 的机器是同一台那 JDK 插件一般已经装好了。如果 pytest 跑在单独的节点上需要在节点上配好 Java 环境。4.2 全局工具配置Allure 命令行安装完插件后到“系统管理 → 全局工具配置”找到 Allure 那一栏点击“新增 Allure”。有两个选择让 Jenkins 自动下载指定版本的 allure-commandline指定一个已经存在的安装路径。我的建议是如果是外网环境让 Jenkins 自动下载省事如果是内网环境先在服务器上手动解压好 allure-commandline然后选择“Install automatically”以外的模式填写已存在的目录路径。注意自动下载的版本和手动部署的版本都建议固定在某一个大版本上不要频繁升级。Allure 的 JSON 结果格式在不同大版本间偶尔会有变化一旦 Jenkins 插件版本和命令行版本不匹配报告可能生成不出来。4.3 新建一个 Pipeline 任务完整 Jenkinsfile 示例我个人更推荐用 Pipeline 而不是 Freestyle project因为 Pipeline 脚本可以入库团队其他成员 review 和复用都方便。下面是一个可以在你项目里直接改改用的 Jenkinsfilepipeline { agent any tools { allure allure-commandline } environment { // 定义虚拟环境路径避免污染全局 Python VENV ${WORKSPACE}/.venv } stages { stage(准备依赖) { steps { sh python3 -m venv ${VENV} ${VENV}/bin/pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple } } stage(执行测试) { steps { sh cd ${WORKSPACE} ${VENV}/bin/pytest --alluredirallure-results --clean-alluredir } } stage(生成报告) { steps { allure includeProperties: false, jdk: , report: allure-report, results: [[path: allure-results]] } } } post { always { // 把报告目录做成构建产物方便随时下载 archiveArtifacts artifacts: allure-report/**, fingerprint: true // 清理临时文件 cleanWs() } } }这里有三个细节值得解释--clean-alluredir参数很重要。如果不加上次构建留下的旧结果文件会和本次的结果文件混在一起报告里会出现大量“过期”的用例数据导致趋势图失真。allure这个步骤是 Allure 插件提供的 DSL。它做的事情是读取allure-results目录下的原始结果调用全局配置的 allure 命令行工具生成 HTML 报告到allure-report目录然后 Jenkins 会在构建页显示一个 Allure Report 的链接。archiveArtifacts把报告目录归档虽然 Allure 插件自带的报告链接已经能看但归档一份在 Jenkins 构建历史里随时可以比对不同构建的报告差异。4.4 Freestyle 项目怎么配如果你还是习惯用 Freestyle project配置步骤是“构建环境”里勾选Allure Commandline选择你装的版本。“构建”步骤里选“执行 shell”输入pytest --alluredirallure-results --clean-alluredir。“构建后操作”里选Allure Report结果路径填allure-results报告路径填allure-report。本质上和 Pipeline 做的事情一样只是入口不同。但多环境或者多分支构建时Pipeline 明显更灵活。4.5 Jenkins 报告插件的权限与构建历史趋势Allure 插件生成报告后构建页面右上角会出现一个“Allure Report”的图标。点进去就是完整的报告页面包含Overview 页面用例总数、通过率、严重级别分布、持续时间分布、缺陷趋势。Categories 页面失败用例的归类可以看到是“产品缺陷”还是“测试代码问题”。Suites 页面按测试套件维度查看用例。Behaviors 页面按 epic/feature/story 维度查看用例这个页面最适合向项目组同步测试进度。Graph 页面历史构建的用例通过趋势对比。关于访问权限如果用的是 Jenkins 默认的基于角色的权限策略只需要给相关人员分配响应 Job 的“阅读”权限报告链接就在构建页里不需要额外配置。如果是想嵌入到团队内部的质量平台可以直接用 iframe 内嵌报告地址Allure 报告是纯静态页面跨域问题不大。5. 一个必须单独聊的话题Allure 报告的清理与历史数据隔离“为什么我的报告里出现了很多不是本次跑的用例”——这是我见过最多的问题没有之一。答案是allure-results 目录没有清理。Allure 的机制是“先收集所有结果文件再统一渲染”。如果上一次构建的结果文件还留在 allure-results 里下一次构建执行 pytest --alluredirallure-results 时新结果文件是“追加”进去的旧文件并不会被自动清除。于是报告里就会混入历史构建的用例数据通过率、执行时间这些统计全部被污染。解决方案有两个在 pytest 命令里带上--clean-alluredir参数pytest 会在写新结果前清空目录在 Jenkins 构建步骤中先生成带时间戳的目录比如allure-results-${BUILD_NUMBER}再让报告插件指定这个目录。第一种方案最省事也是我日常使用的方案。第二种方案适合需要保留历史原始结果做二次分析的场景。我这里建议优先用第一种简单且不容易出错。还要注意一个点如果你在本地跑过 pytest --alluredirallure-results然后又带着这个目录上库或者打包到测试环境也会出现同样的混淆问题。所以项目根目录下的 allure-results 和 allure-report 都应该加进 .gitignore。6. 实测下来最影响报告体验的几个细节严重级别、重试机制、动态标题最后分享几个我在实际使用过程中逐步优化出来的细节它们单个看不太起眼但组合起来对报告体验的提升非常明显。6.1 严重级别驱动冒烟测试Allure 的 severity 注解除了能在报告里做筛选还能配合 pytest 的-m标记做用例选择。比如我习惯在用例上同时打allure.severity(allure.severity_level.CRITICAL)和pytest.mark.smoke然后在 Jenkins 建两个任务冒烟任务执行pytest -m smoke --alluredirallure-results --clean-alluredir全量任务执行pytest --alluredirallure-results --clean-alluredir这样冒烟任务跑得快报告页面上也可以只看 CRITICAL/BLOCKER 级别的用例快速判断当前版本能不能提测。6.2 重试失败的用例Allure 2.7 之后支持重试聚合接口自动化里最常见的失败原因其实是网络抖动、超时或依赖服务未就绪用例本身逻辑没有问题。全量重跑会浪费时间不重跑又会污染报告。我用的方案是 pytest-rerunfailures 配合 Allure 的 retry 机制pip install pytest-rerunfailures运行命令pytest --reruns 2 --reruns-delay 5 --alluredirallure-results --clean-alluredirAllure 2.7 之后的命令行工具会自动把同一用例的重试记录聚合到一条用例下报告里能看到“重试次数”“最后一次执行的结果”而趋势图统计的是最终结果。这样既不会因为一次网络抖动就全盘标红也不会因为重试而把报告的数据搞乱。6.3 用 pytest 参数化提升报告里的用例可读性接口测试里大量用例是同一接口的不同入参组合不要写成一个一个的独立函数。用 pytest 的 parametrize 可以减少代码重复同时 Allure 会把参数展示在报告里import allure import pytest import requests allure.feature(用户中心) allure.story(查询用户) allure.title(查询用户{case_name}) pytest.mark.parametrize(case_name, user_id, expected_code, [ (存在的用户, 1001, 0), (不存在的用户, 9999, 10001), (非法参数, abc, 10002), ]) def test_query_user(case_name, user_id, expected_code): resp requests.get(fhttps://api.example.com/user/{user_id}) assert resp.json()[code] expected_code注意标题里用了{case_name}这个占位符Allure 渲染标题时会自动替换成参数化的值。这样报告里显示的是一条条“查询用户存在的用户”“查询用户非法参数”而不是“test_query_user[0]”“test_query_user[2]”这种不明所以的名字。这个小技巧在用例量大的时候能显著提升报告的可读性。6.4 动态生成 Allure 标题的另一种方式如果标题需要包含运行时的变量比如订单号、时间戳可以在用例内部用allure.dynamic.title()动态修改def test_dynamic_title(): order_id create_order() allure.dynamic.title(f验证订单 {order_id} 的状态流转) # ... 后续断言这个场景在做业务流测试时特别有用整条链路跑完后报告里能看到每一步操作的对象 ID而不需要自己去日志里翻。7. Jenkins 与 Allure 集成时的常见报错和对策集成过程不可能一次就全绿这里整理几个我实际遇到过的问题附带排查方向和解决路径。7.1 allure: command not foundPipeline 里明明写了tools { allure allure-commandline }但执行时还是提示找不要命令。排查方向全局工具配置里的名称是否和 Pipeline 里引用的名称完全一致大小写敏感Jenkins 节点上 Java 版本是否符合要求如果用的是 agent any确认当前构建跑在哪个节点上allure 工具是不是配置在这个节点上。7.2 报告一直转圈加载不出来构建显示成功但打开 Allure Report 页面一直 loading。这个大概率是 allure 命令行生成报告时出错但没有导致 Jenkins 构建失败。去“系统日志”或者 Pipeline 的“生成报告”阶段看日志最常见的错误是Allure command not found或者是 allure 命令运行时因为 Java 版本问题抛异常。处理方式和上一条类似。7.3 报告只显示“No tests found”原因几乎可以肯定pytest 没有成功执行或者 allure-results 目录是空的。在 Pipeline 里加一步“查看 allure-results 目录内容”的调试ls -la ${WORKSPACE}/allure-results/如果目录下没有生成 .json 结果文件检查 pytest 执行阶段是否有报错以及 pytest.ini 里配置的测试目录是否正确。7.4 历史趋势图断开新报告的 “Trend” 页空白Allure 的历史趋势是基于报告目录里的 history 文件。如果每次都把 allure-report 目录清理掉再重新生成历史趋势就断了。在 Jenkins 构建步骤里加一行从上一份报告中复制 history 文件到当前结果目录if [ -d ${WORKSPACE}/allure-report/history ]; then mkdir -p ${WORKSPACE}/allure-results/history cp -r ${WORKSPACE}/allure-report/history/* ${WORKSPACE}/allure-results/history/ fi但这条在 Jenkins 上其实不是必须的因为 Allure 插件在生成报告时会自动从“上一次生成的报告目录”中拷贝 history 到新的报告里。前提是上一次的 allure-report 目录还在工作空间里。所以如果你的 Pipeline 习惯每次构建都cleanWs那趋势图确实会断。我的建议是不要每次构建清理 allure-report或者把 allure-report 放到工作空间之外的一个固定目录里。7.5 构建后 Allure Report 链接 404报告插件声明出来了但点进去是 404。这种情况通常是报告目录没有生成成功或者报告目录路径和插件配置的路径不一致。去 Jenkins 构建页面的“工作空间”里看 allure-report 是否存在如果不存在基本就是 allure 命令行生成阶段出错了重点查那一步的日志。8. 报告生成之后怎么把 Allure 的价值放大到团队层面报告不是生成完就够了它只是质量的“展示层”。在这个链路的最后一环我自己做了两个扩展动作团队反馈很不错。一个是“失败用例自动通知到企业微信/钉钉群”。在 Pipeline 的 post 阶段判断构建结果如果是不稳定或失败解析 allure-results 目录下最新生成的 JSON 结果文件把失败用例的名称和失败原因拼成消息推送到群机器人。这样开发不打开 Jenkins 也知道自己负责的模块有没有挂。另一个是“周报里的质量数据自动抽取”。因为 allure-results 里每个用例文件都记录了 duration、status、fullName、params我写了一个小脚本每周对历史结果文件做聚合统计生成每个模块的用例量、通过率、平均执行时长。这个数据直接进团队的周报比任何人拍脑袋估的数字都有说服力。关于 Allure 的定制化扩展官方提供的 categories.json 可以自定义失败分类。我在项目根目录放了这样一个文件每次生成报告时Allure 会按它重新归类失败原因[ { name: 网络超时, messageRegex: .*(TimeoutError|timed out).*, matchedStatuses: [failed] }, { name: 断言失败, messageRegex: .*(AssertionError).*, matchedStatuses: [failed] }, { name: 环境异常, messageRegex: .*(ConnectionError|HTTPError).*, matchedStatuses: [broken] } ]在 pytest 命令后面加--alluredir allure-results时Allure 命令行会自动读取项目根目录下的 categories.json。这样报告首页的 Categories 页面会直接告诉你这次构建里有多少失败是断言级别的问题、多少是网络环境问题、多少是服务异常。团队看到报告第一反应是“该找谁”而不是“该猜是什么”。这套体系跑起来之后我自己的感受是写用例的心态会发生变化。以前写完用例跑绿了就万事大吉现在反而会刻意在用例里补全 title、步骤描述和附件信息因为报告不只是给自己看更是给整个团队看的“项目健康说明书”。如果你也在纠结怎么让自动化测试的结果更有说服力不妨照着这篇文章把链路搭起来跑一轮真实构建试试体会一下“报告会说话”的区别。
返回列表