You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Azure DevOps Pipeline与TestRail 7.5集成并导入JUnit测试结果?

实现Azure DevOps流水线推送Cypress测试结果到TestRail 7.5

1. 配置TestRail API访问

  • 登录TestRail,进入Administration > Site Settings > API,启用API访问权限
  • 进入个人资料页面(点击右上角头像),生成并复制你的API密钥(注意妥善保管,这是敏感信息)
  • 记录目标项目的Project ID:从项目URL中提取,比如/index.php?/projects/overview/123中的123
  • 记录要关联的Test Suite ID:从测试套件页面URL中提取

2. 调整Cypress测试报告格式

确保Cypress生成的JUnit XML包含可关联TestRail的必要信息:

  • 在cypress.config.js中配置多报告器,指定JUnit输出:
    const { defineConfig } = require("cypress");
    
    module.exports = defineConfig({
      reporter: 'cypress-multi-reporters',
      reporterOptions: {
        configFile: 'reporter-config.json'
      }
    });
    
  • 创建reporter-config.json文件,定义JUnit报告的输出规则:
    {
      "reporterEnabled": "mocha-junit-reporter",
      "mochaJunitReporterReporterOptions": {
        "mochaFile": "cypress/reports/junit/results-[hash].xml",
        "includePending": true,
        "testCaseSwitchClassnameAndName": true
      }
    }
    
  • (推荐)在Cypress测试用例中添加TestRail用例ID标记,方便脚本精准匹配:
    it('用户登录验证 // TestRail ID: C456', () => {
      // 测试逻辑代码
    });
    

3. 在Azure DevOps流水线中添加结果推送任务

3.1 安装依赖包

在流水线中添加Node.js环境配置和依赖安装步骤:

- task: NodeTool@0
  inputs:
    versionSpec: '18.x'
  displayName: '安装Node.js环境'

- script: |
    npm install mocha-junit-reporter cypress-multi-reporters axios xml2js
  displayName: '安装报告处理依赖'

3.2 编写TestRail推送脚本

在代码仓库中创建push-to-testrail.js文件,实现读取JUnit报告、调用TestRail API的逻辑:

const axios = require('axios');
const xml2js = require('xml2js');
const fs = require('fs');
const path = require('path');

// 从环境变量读取TestRail配置
const TESTRAIL_URL = process.env.TESTRAIL_URL;
const TESTRAIL_USER = process.env.TESTRAIL_USER;
const TESTRAIL_API_KEY = process.env.TESTRAIL_API_KEY;
const PROJECT_ID = process.env.TESTRAIL_PROJECT_ID;
const SUITE_ID = process.env.TESTRAIL_SUITE_ID;

// 读取并解析JUnit XML报告
async function parseJUnitReports(reportDir) {
  const testCases = [];
  const files = fs.readdirSync(reportDir).filter(file => file.endsWith('.xml'));
  
  for (const file of files) {
    const xmlData = fs.readFileSync(path.join(reportDir, file), 'utf8');
    const parser = new xml2js.Parser({ explicitArray: false });
    const result = await parser.parseStringPromise(xmlData);
    const suiteCases = Array.isArray(result.testsuites.testsuite.testcase) 
      ? result.testsuites.testsuite.testcase 
      : [result.testsuites.testsuite.testcase];
    testCases.push(...suiteCases);
  }
  return testCases;
}

// 在TestRail中创建新的测试运行
async function createTestRun(runName) {
  const url = `${TESTRAIL_URL}/index.php?/api/v2/add_run/${PROJECT_ID}`;
  const response = await axios.post(url, {
    suite_id: SUITE_ID,
    name: runName,
    include_all: true
  }, {
    auth: { username: TESTRAIL_USER, password: TESTRAIL_API_KEY }
  });
  return response.data.id;
}

// 推送测试结果到指定TestRail运行
async function pushTestResults(testRunId, testCases) {
  const url = `${TESTRAIL_URL}/index.php?/api/v2/add_results_for_cases/${testRunId}`;
  const results = testCases.map(testCase => {
    // 提取TestRail用例ID
    const idMatch = testCase.name.match(/TestRail ID: C(\d+)/);
    const caseId = idMatch ? parseInt(idMatch[1]) : null;
    
    // 映射TestRail状态ID:1=通过,2=失败,3=跳过
    let statusId = 1;
    if (testCase.failure) statusId = 2;
    if (testCase.skipped) statusId = 3;

    return {
      case_id: caseId,
      status_id: statusId,
      comment: testCase.failure ? testCase.failure['#text'] : '测试执行通过'
    };
  }).filter(item => item.case_id !== null);

  await axios.post(url, { results }, {
    auth: { username: TESTRAIL_USER, password: TESTRAIL_API_KEY }
  });
}

// 主执行逻辑
async function main() {
  try {
    const testCases = await parseJUnitReports('cypress/reports/junit');
    const runName = `Azure DevOps流水线运行: ${process.env.BUILD_BUILDNUMBER}`;
    const testRunId = await createTestRun(runName);
    await pushTestResults(testRunId, testCases);
    console.log(`测试结果已成功推送至TestRail,测试运行ID: ${testRunId}`);
  } catch (error) {
    console.error('推送失败:', error.response?.data || error.message);
    process.exit(1);
  }
}

main();

3.3 配置流水线变量并运行脚本

  1. 在Azure DevOps流水线的变量面板中添加以下保密变量:
    • TESTRAIL_URL:你的TestRail实例地址(如https://your-testrail-instance.testrail.io)
    • TESTRAIL_USER:你的TestRail登录邮箱
    • TESTRAIL_API_KEY:你的TestRail API密钥
    • TESTRAIL_PROJECT_ID:目标项目ID
    • TESTRAIL_SUITE_ID:目标测试套件ID
  2. 在YAML流水线中添加脚本执行任务:
- script: |
    node push-to-testrail.js
  displayName: '推送测试结果到TestRail'
  env:
    TESTRAIL_URL: $(TESTRAIL_URL)
    TESTRAIL_USER: $(TESTRAIL_USER)
    TESTRAIL_API_KEY: $(TESTRAIL_API_KEY)
    TESTRAIL_PROJECT_ID: $(TESTRAIL_PROJECT_ID)
    TESTRAIL_SUITE_ID: $(TESTRAIL_SUITE_ID)
    BUILD_BUILDNUMBER: $(Build.BuildNumber)
  condition: succeededOrFailed() # 无论测试是否通过都执行推送

4. 验证结果

流水线运行完成后,登录TestRail进入Test Runs and Results标签页,即可看到以流水线编号命名的新测试运行,其中包含所有匹配到的Cypress测试用例的执行状态和备注信息。


内容的提问来源于stack exchange,提问作者sultan.zarif

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 21:18:36