HarmonyOS5 DevEco Testing与Jenkins集成:每日构建自动触发全量测试

127 阅读2分钟

以下为 ​​DevEco Testing与Jenkins集成的完整自动化测试方案​​,包含每日构建触发、多设备测试和报告生成的ArkTS代码实现:


1. 集成架构设计

image.png


2. Jenkins流水线配置

2.1 基础管道脚本

// Jenkinsfile
pipeline {
    agent any
    triggers {
        cron('H 8 * * *') // 每天上午8点
        pollSCM('* * * * *') // 代码变更时触发
    }
    stages {
        stage('构建') {
            steps {
                sh 'devecocli build --mode release'
            }
        }
        stage('测试') {
            steps {
                sh 'devecocli test --device-group all --report'
            }
        }
        stage('部署') {
            when { 
                expression { currentBuild.resultIsBetterOrEqualTo('SUCCESS') } 
            }
            steps {
                sh 'devecocli deploy --env staging'
            }
        }
    }
    post {
        always {
            archiveArtifacts artifacts: '**/test-report.html'
            slackSend channel: '#build-notify', message: "构建完成: ${currentBuild.result}"
        }
    }
}

2.2 参数化构建

// Jenkinsfile
parameters {
    choice(
        name: 'TEST_LEVEL',
        choices: ['fast', 'full', 'smoke'],
        description: '选择测试级别'
    )
    booleanParam(
        name: 'RUN_ON_REAL_DEVICE',
        defaultValue: false,
        description: '是否使用真机测试'
    )
}

3. DevEco测试任务控制

3.1 测试任务编排

// test-orchestrator.ets
import { TestRunner } from '@ohos.test';
import { DeviceManager } from '@ohos.device';

export async function runDailyTests() {
  const devices = await DeviceManager.getAvailableDevices({
    minApiLevel: 5,
    types: ['phone', 'tv', 'watch']
  });

  const runner = new TestRunner({
    devices,
    testSuites: ['smoke', 'regression'],
    reportDir: './reports'
  });

  await runner.start();
  return await runner.generateReport();
}

3.2 多设备测试策略

// device-strategy.ets
export function getTestConfig(level: string) {
  const strategies = {
    fast: {
      devices: ['phone'],
      testSuites: ['smoke'],
      timeout: 300_000
    },
    full: {
      devices: ['phone', 'tv', 'watch'],
      testSuites: ['smoke', 'regression', 'performance'],
      timeout: 1_800_000
    }
  };
  
  return strategies[level] || strategies.fast;
}

4. 测试报告生成

4.1 多维度报告聚合

// report-aggregator.ets
import { ReportBuilder } from '@ohos.report';

export function buildDailyReport(results) {
  return new ReportBuilder()
    .addSection({
      title: '设备兼容性',
      data: groupByDevice(results)
    })
    .addSection({
      title: '失败用例',
      data: filterFailures(results)
    })
    .addTrendChart({
      metric: 'passRate',
      history: 7
    })
    .generate('daily-report.html');
}

4.2 历史趋势分析

// trend-analysis.ets
export function analyzeTrend() {
  const history = TestHistory.loadLast(7);
  return {
    passRate: calculatePassRateTrend(history),
    flakyTests: detectFlakyTests(history),
    performance: comparePerformance(history)
  };
}

5. 异常处理机制

5.1 失败用例重试

// retry-manager.ets
export async function handleFlakyTests(failures: TestCase[]) {
  const retryQueue = failures.filter(isFlakyTest);
  
  for (const test of retryQueue) {
    const result = await TestRunner.retry(test, 3);
    if (!result.passed) {
      markAsStableFailure(test);
    }
  }
}

function isFlakyTest(test: TestCase): boolean {
  return test.history?.passRate > 0.5;
}

5.2 设备异常处理

// device-fallback.ets
export async function ensureDeviceAvailable(deviceId: string) {
  try {
    await Device.checkHealth(deviceId);
  } catch (err) {
    console.warn(`设备${deviceId}异常: ${err.message}`);
    await DeviceManager.fallbackToEmulator(deviceId);
  }
}

6. 通知与告警

6.1 Slack通知集成

// slack-notifier.ets
import { Slack } from '@ohos.notify';

export function sendTestReport(report: TestReport) {
  const blocks = [
    Slack.section(`*每日构建结果*: ${report.summary.status}`),
    Slack.divider(),
    Slack.section(`通过率: ${report.summary.passRate}%`),
    Slack.context(`失败用例: ${report.summary.failures.length}`)
  ];
  
  Slack.send({
    channel: '#qa-reports',
    blocks,
    attachments: [{
      title: '详细报告',
      url: report.url
    }]
  });
}

6.2 邮件告警

// email-alert.ets
export function sendCriticalAlert(failures: TestCase[]) {
  const critical = failures.filter(f => 
    f.tags.includes('critical')
  );
  
  if (critical.length > 0) {
    Email.send({
      to: 'dev-team@company.com',
      subject: '关键测试失败',
      body: `失败用例:\n${critical.map(t => t.name).join('\n')}`
    });
  }
}

7. 完整集成示例

7.1 主测试入口

// main-test.ets
import { runDailyTests } from './test-orchestrator';
import { buildDailyReport } from './report-aggregator';

async function main() {
  try {
    const results = await runDailyTests();
    const report = buildDailyReport(results);
    
    if (report.summary.failures > 0) {
      await handleFlakyTests(report.details.failures);
    }
    
    return report;
  } catch (err) {
    console.error('测试流程异常:', err);
    process.exit(1);
  }
}

main().then(report => {
  console.log('测试完成:', report.summary);
  process.exit(report.summary.failures > 0 ? 1 : 0);
});

7.2 Jenkins调用脚本

#!/bin/bash
# run-daily-test.sh

# 安装依赖
npm install @ohos/test-runner @ohos/report-builder

# 执行测试
node test/main-test.ets --mode=full

# 处理结果
if [ $? -ne 0 ]; then
  echo "测试失败"
  exit 1
else
  echo "测试成功"
  exit 0
fi

8. 关键集成指标

环节耗时目标质量门禁
构建阶段<5分钟100%编译通过
单元测试<3分钟≥95%通过率
设备测试<15分钟主要场景100%覆盖
报告生成<1分钟包含历史趋势对比

9. 常见问题解决方案

问题现象解决方案技术实现
设备资源不足自动排队机制DeviceQueue.acquire()
测试用例不稳定智能重试策略TestRunner.retry(3)
报告生成超时增量式报告生成ReportBuilder.stream()
Jenkins节点离线自动切换备用节点failoverToSecondary()

10. 优化建议

  1. ​并行测试加速​​:

    // 在runner配置中启用
    new TestRunner({
      parallel: true,
      maxParallel: 3 // 根据Jenkins节点数调整
    })
    
  2. ​测试用例优先级​​:

    // 标记关键测试用例
    @Test({ priority: 'critical' })
    describe('支付流程', () => {
      it('应完成正常支付', () => { ... });
    });
    
  3. ​资源缓存优化​​:

    # Jenkinsfile中缓存node_modules
    cache([
      '**/node_modules',
      '**/build-cache'
    ])
    

通过本方案可实现:

  1. ​无人值守​​ 每日全量测试
  2. ​多设备并行​​ 测试执行
  3. ​智能异常处理​​ 机制
  4. ​可视化​​ 质量趋势分析