以下为 DevEco Testing与Jenkins集成的完整自动化测试方案,包含每日构建触发、多设备测试和报告生成的ArkTS代码实现:
1. 集成架构设计
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. 优化建议
-
并行测试加速:
// 在runner配置中启用 new TestRunner({ parallel: true, maxParallel: 3 // 根据Jenkins节点数调整 }) -
测试用例优先级:
// 标记关键测试用例 @Test({ priority: 'critical' }) describe('支付流程', () => { it('应完成正常支付', () => { ... }); }); -
资源缓存优化:
# Jenkinsfile中缓存node_modules cache([ '**/node_modules', '**/build-cache' ])
通过本方案可实现:
- 无人值守 每日全量测试
- 多设备并行 测试执行
- 智能异常处理 机制
- 可视化 质量趋势分析