ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Allure测试报告实战:从安装配置到CI集成的完整指南

Allure测试报告实战:从安装配置到CI集成的完整指南 测试报告这个东西做自动化的人几乎每天都在碰但真正能让人打开、看懂、愿意反馈的报告其实不多。我入行前几年用的报告方案一直在换从HTMLTestRunner到pytest-html再到自己拿模板块拼出来的页面各有各的问题。直到第一次接触Allure测试报告才觉得测试结果的上限被拉高了一大截。Allure能把用例组织、失败信息、历史趋势、缺陷分类全部收到一套结构化的报告体系里接口自动化、UI自动化、甚至UDS诊断自动化我都用它出过报告效果都很好。这篇文章不是把官方文档念一遍而是基于我的实际使用过程把从环境准备、报告生成到上线使用的完整路径和容易踩的坑一条一条讲清楚里面涉及的配置都来自真实项目。刚接触Allure的人可以照着走已经在用但总觉得报告差点意思的团队也能在里面找到一些调整思路。文章里我也会夹带一些个人判断比如哪些配置值得做、哪些做法容易把自己坑了这些判断未必适合所有项目但至少能在你选择方案时提供一个参考。1. 报告方案对比中的取舍为什么Allure能留下来1.1 那些年我用过的报告方案先说结论Allure不是测试报告工具里唯一的答案但它是我用下来综合成本最低、上限最高的一个。早年的HTMLTestRunner单个HTML文件样式偏老能显示用例名、执行时间、通过率可一旦用例数量上来页面信息就开始拥挤失败堆栈也看不清楚。pytest-html比它好看一些但是碰上失败截图的嵌入、按业务模块归类、历史趋势这些需求还是要自己动手改造。再往上走直接把测试结果输出成JUnit XML交给CI平台自带的报告插件信息是全了但可读性一般汇报的时候很难直接拿给人看。有段时间我还试过自己拼报告模板把每个用例的结果渲染成HTML页面好看是好看了但每个项目都要维护一套模板逻辑得不偿失。Allure的切入点和上述方案不一样。它先把测试执行结果落成一批结构化的result文件再用命令行工具把这些文件渲染成HTML报告。这层抽象带来的好处非常多测试框架换语言了报告体系不变CI平台换了报告依然可以生成想要定制展示改的是数据配置而不是模板代码。对我来说它真正解决了报告能不能长期沉淀的问题。1.2 Allure的能力边界与使用前提能做什么我用一句话概括Allure负责把测试过程变成可以被筛选、被对比、被追溯的结构化信息。用例可以按模块组织步骤可以层层展开失败信息可以附带截图、报文、日志多次执行可以形成趋势缺陷可以按规则自动归类。这些能力正好是团队做质量复盘时最需要的东西。不能做什么也很明确。Allure不执行测试它不取代pytest、JUnit、TestNG这些执行框架它也不替你做根因分析不会告诉你这个BUG是代码问题还是环境问题它更不会因为报告做得漂亮就让质量变好。另一个容易被忽略的前提是想要报告有信息量就得在用例里主动埋点——装饰器、动态标签、附件这些靠的是接入方的自觉。所以每次有人问我Allure好不好用我都会反问他一句你的用例组织方式是否足够规整如果测试本身是乱的Allure只会把乱放大成一份漂亮的乱。2. 环境准备安装Allure最容易翻车的三个点2.1 JDK版本最先栽跟头的地方安装Allure命令行工具之前先确认环境里有JDK。Allure的命令行工具本身是Java程序没有Java环境装完allure之后敲allure --version大概率只会得到一句command not found或者一串看不懂的Java报错。我最早一次在Windows机器上装Allure下载zip包解压、配置PATH折腾了快半小时最后发现是机器上只有JRE没有JDK运行时缺了一堆类气得够呛。版本方面给一个不严谨但省心的经验Allure 2.x基本都能跑在JDK 8上但如果你用的是比较新的commandline版本建议直接装JDK 11或17能避开不少启动时的类加载异常。注意这里说的是commandline版本跟后面要说的allure-pytest这个Python库的版本是两码事别混在一起。2.2 allure-pytest的版本敏感问题Python侧接入Allure核心是装一个库pip install allure-pytest。装完之后pytest会自动识别--alluredir这个参数。这个库对pytest的版本兼容性比较敏感遇到类似AttributeError、PluginValidationError这样的报错先别急着怀疑代码大概率是allure-pytest和你当前pytest版本不匹配。我的习惯是建虚拟环境时先装pytest再装allure-pytest然后立刻跑一个空测试验证。另外提醒一句网上老教程里有个库叫pytest-allure-adaptor那是Allure 1.x时代的产物早就不推荐了搜索安装教程的时候看到这个名字直接跳过。Windows环境下还要注意安装完成后如果发现pytest不认这个插件先确认pip install和执行pytest命令是否在同一个虚拟环境跨环境导致的明明装了却用不了是我见过最多的情况。2.3 安装完怎么确认环境可用给出一个我每次换机器都会走一遍的三步验证。第一步终端执行allure --version看到版本号说明命令行工具OK第二步随便写一个test_demo.py里面放普通的断言跑pytest --alluredirallure-results第三步检查allure-results目录下有没有生成一堆uuid命名的json文件。有说明采集成功没有说明allure-pytest没有被加载。这一步看似简单但很多人的问题就出在这装完工具直接跑真实用例报错之后分不清是环境问题还是代码问题。先拿最小用例验证能帮你把变量减到最少。验证通过后再开始配置pytest.ini这样后面就算出问题也容易定位是哪一行配置引起的。3. 从pytest到报告落地命令、装饰器与动态信息3.1 最简链路先让报告跑起来环境就绪后一条最简链路是这样的pytest --alluredirallure-results收集结果然后allure generate allure-results -o allure-report --clean生成静态报告最后用浏览器直接打开生成目录里的index.html。如果想要临时快速预览也可以用allure serve allure-results命令会自动起一个本地web服务并打开浏览器。我建议第一次跑通的时候不要加太多配置就用一个最简单的用例重点观察两个地方一是命令行输出的执行摘要二是生成的allure-report目录里有没有index.html。跑到这一步整个数据链路就通了后面再加戏就容易很多。至于pytest.ini里的配置我会在后面实战小节给出完整版这里先不急着配避免一出问题分不清是代码问题还是配置问题。3.2 装饰器让报告替你说清楚Allure报告的可读性主要靠装饰器撑起来。feature是模块、story是功能点、title是报告里显示的名称、severity是优先级、link可以关联需求或缺陷。这些装饰器写起来很短但对后期筛选和汇报帮助巨大。import allure allure.feature(订单模块) allure.story(创建订单) allure.title(创建订单-库存不足时返回明确错误) allure.severity(allure.severity_level.CRITICAL) allure.link(https://example.com/requirement/123, name需求链接) def test_create_order_out_of_stock(): with allure.step(准备商品库存数据): assert True with allure.step(调用创建订单接口): assert True这里有一个经常被忽略的点with allure.step(步骤名)写的不是注释而是会真实呈现在报告里的多级步骤结构。失败时点击对应步骤可以直接看到是在哪一步断开的比从头翻堆栈高效很多。实际项目里我习惯把接口调用、数据库断言、数据清理分别放进独立step里这样报告读起来基本就等于一份操作日志。Behaviors页签就是按照feature/story的层级把用例组织起来的CRITICAL级别的用例和普通的用例一眼就能区分。给用例分层还有一个隐性好处筛选的时候可以快速圈定这轮冒烟测什么、回归测什么对团队里不写代码的角色很友好。3.3 动态标签参数化用例的救星参数化用例如果不处理title报告里会出现一堆长得一模一样的用例名只看结果根本不知道哪个参数出问题。用allure.dynamic可以运行时改名常见的做法是把参数里的关键信息拼进title。import pytest import allure test_data [ {case_id: 1, username: alice, expected: 登录成功}, {case_id: 2, username: bob, expected: 密码错误}, ] allure.feature(用户模块) pytest.mark.parametrize(data, test_data, ids[str(d[case_id]) for d in test_data]) def test_login(data): allure.dynamic.title(f登录用例{data[case_id]}{data[username]}) allure.dynamic.story(登录) assert data[expected] in 登录成功需要特别注意allure.dynamic这类动态设置必须在用例实际执行过程中调用写在模块级别或装饰器位置是无效的因为那是收集阶段。如果测试数据是从外部文件读进来的也可以在用例开头把feature、story、severity全部动态设上让报告的组织层级完全跟着数据走。唯一要小心的是别把这些调用放在过早return的分支之后否则用例在跑到断言前就跳了报告里的元信息还是空的。3.4 附件给失败一个完整的现场附件是Allure和普通HTML报告拉开差距的地方。allure.attach适合把字符串内容直接塞进报告比如接口的响应报文、日志片段allure.attach.file适合附加已有的文件比如截图、录制视频、导出文件。attachment_type支持TEXT、JSON、HTML、PNG、JPG、XML等常见格式。import allure # 把接口响应附到报告 allure.attach(response.text, 创建订单接口响应, allure.attachment_type.JSON) # 失败时附截图 allure.attach.file(screenshot_path, 失败页面截图, allure.attachment_type.PNG)什么内容该附我的原则是能帮人复现问题的才附。接口测试附请求体、响应体、关键数据库查询结果UI测试附失败截图、浏览器控制台日志性能测试附压测配置和采样数据。无脑塞一堆大附件只会让报告变慢后面第6章我会专门讲怎么控制报告体积。关于allure.attach和allure.attach.file的适用场景可以简单理解成前者塞文本内容快但体积不可控后者引用文件路径会打包到报告的files目录里更适合图片、视频这类二进制数据。如果只是几十KB的文本直接用attach即可没必要先落盘再引用。4. 报告的可信度工程环境信息、缺陷分类与历史趋势4.1 environment.properties让报告显示环境信息在allure-results目录下放一个environment.properties报告Overview页就会多出一个Environment区块把这些键值对展示出来。这个区块对汇报场景非常有用别人一看就知道这轮测试跑在什么环境、什么版本、什么时间。BrowserChrome Browser.Version118.0 Test.Envstaging Python3.10.12 OSmacOS 14.5这里有一个容易踩的坑Java的properties文件默认按ISO-8859-1解析直接写中文很容易乱码。我现在的做法是一律用英文键值不在这个文件里折腾中文。如果确实需要展示中文描述可以放到后面说的categories定义里或者由测试代码动态写入Unicode转义内容。4.2 categories.json缺陷分类的规则化默认报告里的Categories页签只有Product defects和Test defects两大分类信息粒度太粗。利用categories.json可以自己定义缺陷的分类规则文件同样放在allure-results目录下。[ { name: 断言失败类问题, matchedStatuses: [failed], messageRegex: [.*AssertionError.*] }, { name: 环境或依赖异常, matchedStatuses: [broken], messageRegex: [.*(ConnectionError|Timeout|NameError).*] }, { name: 已知不稳定用例, matchedStatuses: [failed, broken], flaky: true } ]配好之后Categories页签会按这些规则聚合统计。我每次看报告第一眼不是看通过率而是先看Categories断言失败数量上升说明功能逻辑可能有问题环境异常数量上升说明测试环境不稳定或者网络有波动。这个习惯帮我快速判断这轮测试结果能不能信比在Suites列表里逐条翻用例高效太多了。4.3 history与趋势图怎么保留才不空Allure报告里的Trend趋势图数据来自上一次报告里的history目录。很多教程习惯在pytest.ini里写--clean-alluredir每次跑之前清空整个allure-results目录。这样确实能避免残留数据但要注意它会把history目录一起清掉趋势图直接就断了。我现在的做法是不在pytest.ini里配--clean-alluredir而是手动控制。执行完测试后先把上一轮已经生成的allure-report/history复制到新的allure-results目录下再执行allure generate。第一次执行没有history文件跳过复制即可从第二次开始趋势线就连起来了。# 保留历史趋势的常规操作 cp -r allure-report/history allure-results/ 2/dev/null || true allure generate allure-results -o allure-report --clean这里要强调一下执行顺序复制history必须在allure generate之前。如果先generate再复制新报告里包含的还是旧history趋势图不会更新到最新一轮。另外--clean只清输出报告目录里的旧文件不会动allure-results这个参数本身没有问题关键是history文件有没有被复制回来。4.4 executor.json让报告显示CI构建信息如果报告是在CI里跑的很多人会困惑为什么Overview页的Executor区域是空的。因为Allure默认不知道这次执行来自哪个构建。在allure-results下放一个executor.jsonOverview的Executor区块就能显示CI名称、构建号、构建URL。{ name: Jenkins, type: jenkins, url: https://jenkins.example.com, buildName: daily-run-123, buildUrl: https://jenkins.example.com/job/api_auto/123 }Jenkins里跑的时候这些信息可以从环境变量动态生成GitLab CI同理。有了这个报告里的每个执行记录都能追溯到具体的构建和代码版本。这个文件虽然只有几行但实际价值很大尤其当一份报告要同时服务多个团队时能避免这是哪次跑的是不是最新代码这类反复被问的问题。5. 真实项目里的落地方式从接口测试到UDS诊断自动化5.1 一个顺手项目的目录结构以我维护过的一段接口自动化为例外加之前短暂接触的UDS诊断协议栈自动化结构上基本是同一套思路。测试用例按业务模块拆文件公共封装放common测试数据放config或外部YAMLpytest.ini里只配框架行为不配业务逻辑allure-results和allure-report都是生成目录只在处理history时手动动一下。api_auto/ ├── pytest.ini ├── requirements.txt ├── common/ │ ├── client.py │ └── log.py ├── config/ │ └── env.py └── tests/ ├── conftest.py ├── test_login.py └── test_order.pypytest.ini里我放的内容比较克制[pytest] testpaths tests addopts -q --alluredirallure-results线上跑的时候我会在外层命令里再追加其它参数而不是把所有选项都焊死在addopts里这样临时想跑一遍不带报告的命令也方便。很多项目喜欢把所有pytest选项全堆进addopts短期内没毛病但等你需要灵活调整执行范围时就会难受。5.2 conftest.py里统一做失败现场采集用例里写不写附件是个人习惯但失败时的现场信息最好统一在conftest.py里处理。我用pytest_runtest_makereport钩子在用例执行失败时把关键数据附加到报告里。这里有个细节如果项目里已经把响应封装在某个对象里可以在会话语境里取出来如果没有也可以在用例里通过with allure.step包装并显式attach。两种方式本质是同一件事让失败信息在报告里集中出现而不是散落在各个用例中。import allure import pytest pytest.hookimpl(tryfirstTrue, hookwrapperTrue) def pytest_runtest_makereport(item, call): outcome yield report outcome.get_result() if report.when call and report.failed: # session级别的自定义上下文由公共封装在用例执行时写入 context getattr(item, _login_context, None) if context is not None: allure.attach(context.response_text, 失败时响应, allure.attachment_type.TEXT) longrepr getattr(report, longreprtext, ) or str(getattr(report, longrepr, ) or ) allure.attach(longrepr, 失败堆栈, allure.attachment_type.TEXT)要说明一下长堆栈内容本身Allure会记录这里attach的是方便查看者快速定位的副本两者信息会有重叠但实际看报告时附件的存在能减少点击次数。具体怎么取数据每个项目的封装不同核心逻辑都一样在失败打点处把当时能拿到的现场信息塞进报告。5.3 重试用例在报告里的表现接入了pytest-rerunfailures之后报告里会用Flaky标签标出重试过的用例这是Allure比较贴心的设计。不过这里有个版本配合的问题allure-pytest和pytest-rerunfailures都跟着pytest版本更新走遇到重试后报告没有Flaky标记、或者报错说hook签名不对优先检查三个库的版本组合。我一般会固定一套验证过的版本组合写进requirements.txt而不是每次pip install拉到最新。从结果上看重试本来就该被视为不稳定信号而不是成功与否。所以我在看报告时对Flaky用例的态度是把它当成测试环境不稳定的报警器攒够了就去找原因而不是在报告里默默忽略。有些团队为了让通过率好看给所有用例都开了重试结果报告一片绿灯但那个绿灯的含金量非常低这是在自欺欺人。5.4 在Jenkins和GitLab流水线里出报告本地怎么玩都行放到CI里才是常态。Jenkins如果有Allure插件最简单的做法是直接用allure函数。流水线写法大致如下stage(自动化测试) { steps { sh pytest --alluredirallure-results } post { always { allure([ commandline: allure-commandline, results: [[path: allure-results]], report: allure-report, clean: true ]) } } }没有插件或者不想装插件就在脚本里直接执行allure generate然后把allure-report作为构建产物归档。GitLab CI里把报告放到artifacts的paths里团队成员就能在流水线页面下载或在线浏览。test: stage: test script: - pytest --alluredirallure-results - allure generate allure-results -o allure-report --clean artifacts: when: always paths: - allure-report expire_in: 7 days这里再提一下UDS诊断自动化。之前有段时间我维护的UDS诊断协议栈自动化底层跑在canoe和TSMaster的仿真环境里控制层用pytest组织每个诊断服务比如0x10会话控制、0x22读数据都有正反向用例。报告最后同样用Allure汇总Behaviors页签按诊断服务分组开发定位问题很快。所以别看Allure常被当成Web自动化工具它和具体业务其实是完全解耦的关键在于用例组织得好不好。6. 实际使用中反复踩过的坑与我的处理习惯6.1 中文乱码的重新认识乱码分几种处理方式完全不同。第一种是allure命令行在Windows控制台输出乱码通常是代码页问题执行chcp 65001切到UTF-8能缓解。第二种是environment.properties里中文乱码上面说过properties默认ISO-8859-1最好别直接写中文。第三种是测试代码里的中文日志在报告里乱码多半是日志写入时用的编码和报告读取时不一致统一用UTF-8基本能解决。遇到乱码先别急着改文件先分清楚是哪个环节的编码问题。曾经有个项目报错信息里中文全都变成问号排查了半天最后发现是conftest.py里的log handler用了GBK编码写文件Allure读取时按UTF-8解析两边对不上。这种问题跟Allure本身没关系但会直接反映在报告里容易被当成Allure的锅。6.2 趋势图空白与历史数据断档趋势图空白是最常见的报告看起来没毛病但总觉得少点东西的情况原因基本就是history目录断档。这里再强调一遍处理顺序复制history到allure-results然后allure generate。如果已经不小心清了也没关系趋势图会从头开始不会报错只是历史线条没了。我习惯把这个复制动作写进构建脚本里而不是靠记忆。因为人一旦忙起来很容易忘记这个步骤。CI流水线的稳定运行靠的是脚本可重复不是人的记性。你可以在Jenkins流水线的sh块里加一行复制命令或者在GitLab CI的script列表里写和本地操作完全一致。6.3 allure serve在远程服务器上的尴尬allure serve适合本地开发时快速预览但如果你在服务器或CI执行机上跑它启动的web服务很可能不是外界能直接访问的而且serve是前台阻塞进程不适合放进流水线。我在服务器上从来不用serve一律用allure generate生成静态报告然后让CI平台或nginx把报告目录暴露出来。报告本身是纯静态文件拷贝、归档、邮件附件都方便。如果团队有长期留存报告的需求把这个静态目录挂到对象存储或者共享盘上会比每次现开serve靠谱得多。现在很多团队的实践是报告生成后直接推送到内部文档平台只留一个链接在群里这个思路我很推荐。6.4 报告越用越慢的优化随着用例增多和附件堆积生成的报告会越来越大打开越来越慢。我一般做三件事第一附件挑重点不把每一次请求响应都塞进报告只在失败或关键断言处附加第二图片先压缩再附加一张几MB的截图直接塞进去网页加载不会快第三在CI里设置报告产物过期清理比如GitLab里expire_in设成7天需要长期归档的单独打包存到对象存储。这里分享一个我踩过的具体案例有一次接口自动化加了一大批数据库查询的日志附件每个用例都附上几千行的SQL执行结果报告从几MB涨到了四十多MB打开一次要几十秒。后来我改成只在失败时附数据库查询记录报告体积立刻降下来了而且排查问题时反而更聚焦。报告应该像体检报告一样每次看的是当轮结果的关键指标而不是把数据库原始日志整个塞进去。6.5 一些长期使用养成的习惯最后说几个我自己的小习惯不一定适合所有团队但可以供参考。第一个用例里习惯性地把关键业务用例用allure.title写成人类能懂的描述而不是函数名方便开发一起看报告。第二个每次发布版本后把allure-report压缩归档按日期命名之后回溯问题直接翻对应的归档包。第三个定期清理不再需要的旧用例Allure报告里留着已经被废弃的业务用例除了干扰判断没有别的作用。另外categories.json和environment.properties这两个文件我会放进版本管理作为项目的一部分。随着用例增长缺陷分类规则会越调越准环境信息也会越加越全这些属于团队的测试资产应该跟着代码走而不是躺在某台机器的临时目录里。做测试框架的时间越长我越觉得报告不是给机器看的而是给人和人之间的决策看的。Allure本身不会替你发现缺陷但一份组织良好的Allure测试报告能让人更快地看出问题在哪、影响面多大、是环境问题还是功能问题。我现在只要条件允许接手自动化项目的第一件事就是把Allure接进来把categories和environment配置好因为我知道后面所有复盘、汇报、排查都会因此省下大量时间。
返回列表