如何为Playwright的JUnit Reporter添加自定义Xray属性及使用扩展属性?
在Playwright中使用带Xray扩展属性的JUnit Reporter
能否使用?
可以。Xray支持解析标准JUnit XML报告,同时允许通过自定义属性(如testKey、requirementKey等)扩展报告内容,实现测试结果与Jira/Xray测试用例的关联。Playwright的内置JUnit Reporter生成的报告符合标准格式,在此基础上添加Xray自定义属性后,即可被Xray正常识别处理。
如何添加自定义Xray属性?
方法1:自定义Playwright JUnit Reporter
通过扩展Playwright内置的JUnit Reporter,在测试结束时自动添加Xray所需的自定义属性:
- 创建自定义Reporter文件(如
xray-junit-reporter.ts):
import { Reporter, TestCase, TestResult } from '@playwright/test/reporter'; import { JUnitReporter } from '@playwright/test/reporters/junit'; class XrayJUnitReporter extends JUnitReporter { override onTestEnd(test: TestCase, result: TestResult) { super.onTestEnd(test, result); // 从测试注解中获取Xray属性 const testKey = test.annotations.find(a => a.type === 'testKey')?.description; const requirementKey = test.annotations.find(a => a.type === 'requirementKey')?.description; // 获取对应测试用例的XML元素(注:若父类私有属性不可访问,可改用XML后处理方式) const testCaseElement = (this as any)._getTestCaseElement?.(test); if (testCaseElement && (testKey || requirementKey)) { // 创建或获取properties节点 let propertiesElement = testCaseElement.querySelector('properties'); if (!propertiesElement) { propertiesElement = testCaseElement.ownerDocument.createElement('properties'); testCaseElement.appendChild(propertiesElement); } // 添加testKey属性 if (testKey) { const prop = testCaseElement.ownerDocument.createElement('property'); prop.setAttribute('name', 'testKey'); prop.setAttribute('value', testKey); propertiesElement.appendChild(prop); } // 添加requirementKey属性 if (requirementKey) { const prop = testCaseElement.ownerDocument.createElement('property'); prop.setAttribute('name', 'requirementKey'); prop.setAttribute('value', requirementKey); propertiesElement.appendChild(prop); } } } } export default XrayJUnitReporter;
- 在测试用例中添加注解传递Xray属性:
import { test, expect } from '@playwright/test'; test('用户登录验证', { annotations: [ { type: 'testKey', description: 'TEST-456' }, { type: 'requirementKey', description: 'REQ-789' } ] }, async ({ page }) => { await page.goto('/login'); await page.fill('#user-input', 'test-user'); await page.fill('#pass-input', 'test-pass'); await page.click('#submit-btn'); await expect(page).toHaveURL('/home'); });
- 在
playwright.config.ts中配置使用自定义Reporter:
import { defineConfig, devices } from '@playwright/test'; import XrayJUnitReporter from './xray-junit-reporter'; export default defineConfig({ reporter: [ ['list'], // 保留控制台输出 [XrayJUnitReporter, { outputFile: 'junit-xray-results.xml' }] ], // 其他配置项... });
方法2:后处理生成的JUnit XML文件
如果不想自定义Reporter,可在测试完成后用脚本修改生成的XML文件,添加Xray属性:
- 先使用Playwright内置JUnit Reporter生成基础报告:
// playwright.config.ts export default defineConfig({ reporter: [ ['list'], ['junit', { outputFile: 'junit-results.xml' }] ], });
- 编写Node.js脚本(如
add-xray-props.js)修改XML:
const fs = require('fs'); const { xml2js, js2xml } = require('xml-js'); // 读取原始JUnit报告 const rawXml = fs.readFileSync('junit-results.xml', 'utf8'); const xmlObj = xml2js(rawXml, { compact: true, spaces: 2 }); // 遍历测试用例添加Xray属性 const processTestCases = (testsuite) => { const testcases = Array.isArray(testsuite.testcase) ? testsuite.testcase : [testsuite.testcase]; testcases.forEach(testcase => { // 初始化properties节点 testcase.properties = testcase.properties || { property: [] }; if (!Array.isArray(testcase.properties.property)) { testcase.properties.property = [testcase.properties.property]; } // 添加自定义属性(这里可根据测试名称或其他规则动态赋值) testcase.properties.property.push({ _attributes: { name: 'testKey', value: 'TEST-123' } }); testcase.properties.property.push({ _attributes: { name: 'labels', value: 'smoke,ui-test' } }); }); }; // 处理所有测试套件 if (Array.isArray(xmlObj.testsuites.testsuite)) { xmlObj.testsuites.testsuite.forEach(processTestCases); } else { processTestCases(xmlObj.testsuites.testsuite); } // 保存修改后的XML const modifiedXml = js2xml(xmlObj, { compact: true, spaces: 2 }); fs.writeFileSync('junit-xray-results.xml', modifiedXml);
- 测试完成后运行脚本:
node add-xray-props.js
生成的带Xray属性的XML报告,即可上传至Xray完成测试结果的关联与分析。
内容的提问来源于stack exchange,提问作者MiklosBalazsi
相关产品推荐
相关产品推荐

