WebdriverIO Allure Reporter 集成实战:从 Test Plan 精准筛选到 Allure 报告生成
【免费下载链接】webdriverioNext-gen browser and mobile automation test framework for Node.js项目地址: https://gitcode.com/GitHub_Trending/we/webdriverio
导读
@wdio/allure-reporter是 WebdriverIO 生态中用于产出 Allure 测试报告 的官方 reporter 插件。本文基于当前仓库packages/wdio-allure-reporter/的实现与测试,完整讲解该插件的安装配置、全部 reporter 选项、Test Plan 精准测试筛选、Allure API 的标签/步骤/附件用法,以及如何在命令行、onComplete钩子和 Jenkins 中展示报告。读完本文,你将能在一套 WebdriverIO 工程里快速产出高质量、可回溯、支持精选执行与 CI/CD 集成的 Allure 报告。
插件定位与工作原理
从源码结构看,该插件是一个继承自@wdio/reporter的AllureReporter类(见 src/reporter.ts)。它订阅 WebdriverIO runner 的onRunnerStart、onSuiteStart、onTestStart、onTestPass、onTestFail、onBeforeCommand、onAfterCommand等一系列生命周期事件,将测试运行产生的结构、步骤、错误、截图与请求响应等统一转换成 Allure 内部的 runtime 消息,再通过allure-js-commons的FileSystemWriter写入outputDir指定的结果目录。每个 spec 会落盘一份 JSON 结果文件,并附带若干.txt、.png等附件。
插件依赖关系(见 package.json):@wdio/reporter、@wdio/types、allure-js-commons、csv-stringify(用于把 Cucumber Data Table 转成 CSV 附件)等,要求 Node.js >= 18.20.0。
安装
推荐将@wdio/allure-reporter作为devDependency加入项目的package.json:
{ "devDependencies": { "@wdio/allure-reporter": "^7.0.0" } }或直接通过命令行安装:
npm install @wdio/allure-reporter --save-dev在 wdio.conf.js 中启用并配置 reporter
在 WebdriverIO 配置文件的reporters数组中启用插件。采用数组形式可以把配置选项作为第二个参数传入:
export const config = { // ... reporters: [['allure', { outputDir: 'allure-results', disableWebdriverStepsReporting: true, disableWebdriverScreenshotsReporting: true, addConsoleLogs: true, // Attach console logs to reports reportedEnvironmentVars: { 'NODE_VERSION': process.version, 'BROWSER': 'chrome' } }]], // ... }配置选项详解
这些选项的完整类型定义可以在 src/types.ts 中找到,每个选项都会被传递进底层ReporterRuntime:
outputDir:结果输出目录,默认./allure-results。测试运行结束后,该目录会为每个 spec 生成一个 JSON 文件,并包含若干.txt、.png文件及其他附件。在 reporter.ts 中,FileSystemWriter的resultsDir即取自outputDir(未设置时回退到resultsDir或默认值allure-results)。disableWebdriverStepsReporting:可选,默认false。设为true后只记录自定义步骤,WebdriverIO 底层执行的 WebDriver 命令步骤将不再进入报告。对应实现在onBeforeCommand/onAfterCommand(reporter.ts),当该选项为真时会直接跳过命令步骤的生成。issueLinkTemplate:可选,指定 issue 链接模板。reporter 会把{}占位符替换成addIssue(value)调用传入的值;使用 Cucumber 时,任意层级设置了issue标签也会被转换成链接。示例:https://example.org/issue/{}。在源码中,模板中的{}会被先规范化为%s再交给链接模板解析(reporter.ts)。tmsLinkTemplate:可选,指定 TMS(测试管理系统)链接模板。{}占位符会被替换成addTestId(value)传入的值;Cucumber 的testId标签同理。示例:https://example.org/tms/{}。disableWebdriverScreenshotsReporting:可选,默认false。设为true后不再自动附加截图。useCucumberStepReporter:可选,默认false。使用 Cucumber 时设为true可以改变报告层级结构(Feature/Scenario/Step 的展示方式)。disableMochaHooks:可选,默认false。设为true后不再把 Mocha/Jasmine 的before/after钩子堆栈、截图与结果引入报告。在onHookStart/onHookEnd中会据此跳过钩子事件(reporter.ts)。addConsoleLogs:可选,默认false。设为true后将步骤期间的 console 输出作为附件附加到报告。其实现方式是临时包装process.stdout.write收集输出,并在步骤/测试结束时以Console Logs附件写入(reporter.ts)。reportedEnvironmentVars(类型:Record<string, string>):把自定义环境变量展示在报告中。注意该选项只影响报告展示,并不会修改真实的环境变量。运行结束时onRunnerEnd会调用_allureRuntime.writeEnvironmentInfo()将这些变量写入报告(reporter.ts)。
Test Plan:只执行测试计划中定义的部分用例
Test Plan 功能允许你通过一个 JSON 文件声明本次要运行的用例子集,非常适合 CI/CD 流水线中的定向回归、并行执行或优先级测试。
创建测试计划文件
在项目根目录创建.allure/testplan.json或testplan.json:
{ "version": "1.0", "tests": [ { "id": "test-001", "selector": "test/index.test.ts#should generate testplan.json" } ] }Selector 的匹配机制
Test Plan 的 selector 是基于测试的fulltitle(包含文件路径与测试名称)进行匹配的,格式为:
<file-path>#<test-name>匹配方式非常灵活,支持以下三类:
- 精确匹配:使用完整的测试标题。
- 部分匹配:使用测试标题的子串。
- 文件级匹配:带上文件路径实现精准定位。
典型示例:
test/index.test.ts#should generate testplan.json:匹配特定文件中的特定测试。Login Tests:匹配标题中包含Login Tests的任何测试。User Registration:匹配标题中包含User Registration的任何测试。
从源码看,匹配逻辑远比"单一字符串相等"复杂:在 src/testplan.ts 中,applyTestPlanLabel会基于fullName/fullTitle与文件路径构造出一组候选字符串(包括文件路径#标题、相对路径#标题、文件名#标题以及 suite 与用例之间的空格/点号组合等),只要其中任何一个被allure-js-commons的includedInTestPlan判定命中,该用例即被纳入执行。
启用方式
设置环境变量ALLURE_TESTPLAN_PATH,reporter 会自动加载测试计划文件并只执行与 selector 匹配的测试:
ALLURE_TESTPLAN_PATH=/path/to/your/testplan.json在 reporter.ts 中,构造函数读取该环境变量并调用parseTestPlan()解析计划;testplan.ts 还提供autoInstallMochaFilter():当WDIO_FRAMEWORK包含mocha且设置了该环境变量时,会自动包装全局的describe/context/it/specify,在测试注册阶段就直接过滤掉未命中的用例(it被替换为空实现),从源头实现"只执行计划内的测试"。
使用示例
示例 1:按文件 + 测试名精确指定
{ "version": "1.0", "tests": [ { "id": "login-001", "selector": "tests/auth.test.js#should login with valid credentials" }, { "id": "login-002", "selector": "tests/auth.test.js#should reject invalid credentials" } ] }示例 2:按标题部分匹配
{ "version": "1.0", "tests": [ { "id": "smoke-001", "selector": "Login Tests" }, { "id": "smoke-002", "selector": "User Registration" } ] }示例 3:运行某个文件中的全部测试
{ "version": "1.0", "tests": [ { "id": "auth-suite", "selector": "tests/auth.test.js" } ] }仓库中的测试 tests/testplan.test.ts 验证了过滤行为:在一个包含两个用例的 suite 中,仅匹配到should login with valid credentials 2-1的用例被注册,另一个用例不会执行。Cucumber 场景则通过_decideCucumberSkip(reporter.ts)在场景开始时决定是否跳过,命中的场景会写入ALLURE_TESTPLAN_SKIP标签并以 SKIPPED 状态结束。
Supported Allure API
Allure API 在测试代码中通过@wdio/allure-reporter的默认导出对象访问。
引入方式
CJS:
const allureReporter = require('@wdio/allure-reporter').defaultESM:
import allureReporter from '@wdio/allure-reporter'核心 API:标签类
addLabel(name, value):为测试添加自定义标签。addFeature(featureName):为测试指定功能(feature)。addStory(storyName):为测试指定用户故事(story)。addSeverity(value):指定严重级别,可取值为blocker、critical、normal、minor、trivial。addTag(value):为测试添加标签(tag)。addEpic(value):为测试添加 epic 标签。addOwner(value):为测试添加 owner 标签。addSuite(value)/addSubSuite(value)/addParentSuite(value):为测试添加 suite / 子 suite / 父 suite 标签。addIssue(value):为测试关联 issue id。addAllureId(value):关联 Allure Test Ops 中的实体 id 标签。addTestId(value):关联 TMS 测试 id。:已废弃且不再生效,请改用配置中的addEnvironment(name, value)reportedEnvironmentVars。
附件与内容类
addAttachment(name, content, [type]):为测试保存附件。name(String):附件名。content:附件内容。type(String,可选):附件 MIME 类型,默认text/plain。
addArgument(name, value):为测试添加额外参数。addDescription(description, [type]):为测试添加描述。description(String):测试描述。type(String,可选):描述类型,默认text,可取['text', 'html', 'markdown']。
步骤类
addStep(title, [{content, name = 'attachment'}], [status]):为测试添加一个步骤。title(String):步骤名。content(String,可选):步骤附件内容。name(String,可选):附件名,默认attachment。status(String,可选):步骤状态,默认passed,必须为"failed"、"passed"或"broken"。
startStep(title):开始一个步骤。title(String):步骤名。
endStep(status):结束一个步骤。status(String,可选):步骤状态,默认passed,必须为"failed"、"passed"或"broken"。
step(name, body):以内容函数方式开始步骤,可创建无限层级的嵌套步骤。body(Function):步骤体异步函数。
这些 API 的底层实现位于 src/common/api.ts,它们通过allure-js-commons提供的label、feature、story、step、attachment等原语完成事件上报,再经constants.ts中定义的事件名(如allure:startStep、allure:endStep)转发给 reporter 处理。
Mocha 示例
describe('Suite', () => { it('Case', () => { allureReporter.addFeature('Feature') }) })Cucumber 示例
Given('I include feature and story name', () => { allureReporter.addFeature('Feature_name'); allureReporter.addStory('Story_name'); })自定义步骤(无限层级嵌套)
step方法把每个步骤封装为异步函数,第一个参数是当前步骤上下文,拥有大部分 Allure API 方法(如label、epic、attach等),因此可以构造任意层级的步骤树:
allureReporter.step('my step name', async (s1) => { s1.label('foo', 'bar') await s1.step('my child step name', async (s2) => { // 在 body 函数中可以任意组合步骤 }) })Cucumber 标签转换
Cucumber 中名为issue与testId的特殊标签会被转换成链接(需要先配置对应的issueLinkTemplate/tmsLinkTemplate):
@issue=BUG-1 @testId=TST-2 Feature: This is a feature with global tags that will be converted to Allure links @issue=BUG-3 @testId=TST-4 Scenario: This is a scenario with tags that will be converted to Allure links Given I do something名为feature的特殊标签会被映射为 Allure 标签(label):
Feature: Test user role @feature=login Scenario: Login Given I test login从源码看,onSuiteStart/onSuiteRetry中会把场景标签通过convertSuiteTagsToLabels解析(utils.ts),其中issue与testId走链接生成逻辑,其余标签一律作为普通 label 写入。
展示报告
Allure 提供了多种方式消费allure-results目录中的结果。
命令行
安装 Allure 命令行工具,然后处理结果目录:
allure generate [allure_output_dir] && allure open该命令会默认在./allure-report生成报告,并在浏览器中打开。
自动生成报告(onComplete 钩子)
也可以通过程序化方式在每次运行结束时自动生成报告。先安装工具包:
npm i allure-commandline然后在wdio.conf.js中扩展onComplete钩子(或创建一个自定义 service 来封装该逻辑):
// wdio.conf.js const allure = require('allure-commandline') export const config = { // ... onComplete: function() { const reportError = new Error('Could not generate Allure report') const generation = allure(['generate', 'allure-results', '--clean']) return new Promise((resolve, reject) => { const generationTimeout = setTimeout( () => reject(reportError), 5000) generation.on('exit', function(exitCode) { clearTimeout(generationTimeout) if (exitCode !== 0) { return reject(reportError) } console.log('Allure report successfully generated') resolve() }) }) } // ... }Jenkins 集成
在 Jenkins 中安装并配置 Allure Jenkins 插件 即可把报告接入流水线,Allure 报告界面的 Jenkins Executor 信息也会自动呈现。
附加截图到报告
使用 WebdriverIO 的takeScreenshot函数可以在 Mocha/Jasmine 的afterTest钩子或 Cucumber 的afterStep钩子中把失败截图附加到报告。前提是先确保 reporter 选项中disableWebdriverScreenshotsReporting: false。
Mocha / Jasmine
afterTest: async function(test, context, { error, result, duration, passed, retries }) { if (error) { await browser.takeScreenshot(); } }Cucumber
afterStep: async function (step, scenario, { error, duration, passed }, context) { if (error) { await browser.takeScreenshot(); } }正如上面示例所示,一旦调用该函数,截图就会被附加到 Allure 报告中。从实现上看,onAfterCommand会识别截图命令(utils.ts 中的isScreenshotCommand同时识别 WebDriver 协议的/screenshotendpoint 与 DevTools 协议的takeScreenshot命令),并把 base64 内容以 PNG 附件写入(reporter.ts)。
错误状态判定与多浏览器参数
该插件在判定测试失败状态时有一套细腻的逻辑(utils.ts):
- Jasmine 框架的失败统一记为
FAILED; - 其余框架下,错误信息或堆栈以
assertionerror开头或包含expect时判定为FAILED(断言失败),否则判定为BROKEN(环境性中断)。
同时,每次测试开始时会基于 capabilities 生成browser/device参数与由「完整标题 + 环境标识」计算出的historyId/testCaseId(reporter.ts),这正是 Allure 报告中趋势(TREND)与重试分组能够跨运行稳定聚合的基础,也让多浏览器并行运行时各环境的用例彼此区分。
兼容性
- Allure:与 Allure Framework 3.x 兼容(插件基于
allure-js-commonsSDK 实现)。
获取帮助
- 参考 Allure 官方文档;
- 在 Webdriverio 仓库 Issues 或 Allure3 仓库 中反馈问题。
【免费下载链接】webdriverioNext-gen browser and mobile automation test framework for Node.js项目地址: https://gitcode.com/GitHub_Trending/we/webdriverio
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考