
摘要:本文作为系列第八篇,系统性地构建 Flutter 应用在 OpenHarmony 平台上的全链路测试体系,涵盖 Dart 层单元/集成测试、原生插件 NAPI 测试、HAP 包兼容性验证、多设备 UI 自动化及 CI/CD 集成。通过代码模板、DevEco Test 工具截图、测试覆盖率报告与故障注入案例,帮助团队实现“高质量交付、零回归上线”的工程目标。

与 Android/iOS 不同,OpenHarmony 生态具有以下特点,显著提升测试复杂度:
因此,自动化、分层、可度量的测试体系成为项目成功的基石。
graph TD
A[UI 自动化测试<br>(真机/HAP)] -->|5%| B[集成测试<br>(Dart + Plugin)]
B -->|20%| C[单元测试<br>(纯 Dart 逻辑)]
C -->|75%| D[静态分析 & Lint]✅ 黄金比例:75% 单元测试 + 20% 集成测试 + 5% UI 自动化,兼顾速度与覆盖。
test/
├── core/
│ └── device_manager_test.dart ← 业务逻辑
├── services/
│ └── ohos_bridge_test.dart ← 插件接口 Mock
└── utils/
└── date_formatter_test.dartmockito 模拟平台能力// ohos_bridge_test.dart
import 'package:mockito/mockito.dart';
class MockOhosBridge extends Mock implements OhosBridge {}
void main() {
late MockOhosBridge mockBridge;
setUp(() {
mockBridge = MockOhosBridge();
// 注入 Mock 到业务类
DeviceManager().bridge = mockBridge;
});
test('turn on light should call bridge', () async {
when(mockBridge.turnOn('light_01')).thenAnswer((_) async => true);
await DeviceManager().toggleDevice('light_01');
verify(mockBridge.turnOn('light_01')).called(1);
});
}# 运行测试
flutter test
# 生成覆盖率报告
flutter test --coverage
genhtml coverage/lcov.info -o coverage/html📊 目标:核心模块覆盖率 ≥ 85%。
OpenHarmony 插件通常包含 C++(NAPI)和 TS 两部分。使用 Hypium 测试框架(OpenHarmony 官方)验证 NAPI 行为。
ohos/test/napi/sensor_plugin.test.tsimport { describe, it, expect } from '@ohos/hypium';
describe('SensorPlugin NAPI Test', function () {
it('should return valid accelerometer data', async (done) => {
const result = await callNapiMethod('startAccelerometer');
expect(result.x).toBeNumber();
expect(result.y).toBeNumber();
expect(result.z).toBeNumber();
done();
});
});🔧 需在
module.json5中声明测试 Ability。
// integration_test/device_flow_test.dart
import 'package:integration_test/integration_test.dart';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
testWidgets('Control light flow', (tester) async {
await tester.pumpWidget(const MyApp());
await tester.tap(find.text('客厅灯'));
await tester.pumpAndSettle();
// 验证状态变更
expect(find.text('已开启'), findsOneWidget);
// 验证底层调用(通过 Mock)
verify(mockBridge.turnOn('living_room_light')).called(1);
});
}运行命令:
flutter drive --driver=test_driver/integration_test.dart \
--target=integration_test/device_flow_test.dart使用 hdc 脚本批量测试安装:
#!/bin/bash
# test_hap_install.sh
devices=("phone_rk3568" "tablet_hi3516" "watch_bes2600")
for device in "${devices[@]}"; do
echo "Testing on $device"
hdc -t $device shell bm install -p entry.hap
if [ $? -ne 0 ]; then
echo "❌ Install failed on $device"
exit 1
fi
done
echo "✅ All devices passed"OpenHarmony 不同版本 SDK 存在差异。使用 API Check 工具扫描:
ohos-api-check --hap=entry.hap --target-sdk=4.1输出示例:
[WARN] Used @ohos.bluetooth v3.2, but minSdkVersion=3.1 → Risk on old devices
[OK] All permissions declaredOpenHarmony 提供基于 ArkUI 的 UI 自动化能力,可驱动 Flutter 应用(需启用 Accessibility)。
ui_test/light_control_ui_test.etsimport { driver, By } from '@ohos/uiTest';
export default async function () {
const d = driver();
await d.gotoApp('com.example.smarthome');
// 点击“客厅灯”卡片
const lightCard = await d.findComponent(By.text('客厅灯'));
await lightCard.click();
// 验证开关状态
const status = await d.findComponent(By.text('已开启'));
expect(status.exists()).toBeTruthy();
}📱 需在
config.json中启用debuggable: true。
由于 Flutter 自绘 UI,传统 resource-id 无效。解决方案:
启用语义标签(Semantics)作为测试 hook:
Semantics(
container: true,
label: 'test.light.switch',
child: Switch(...),
)在 DevEco 中通过 accessibilityLabel 查找:
d.findComponent(By.accessibilityLabel('test.light.switch'))name: OHOS Flutter Test Pipeline
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Flutter & OHOS CLI
run: |
flutter pub get
npm install -g @ohos/flutter-cli
- name: Run Unit Tests
run: flutter test --coverage
- name: Build HAP
run: ohos-flutter build --release
- name: Run Integration Tests (Emulator)
run: ohos-flutter test --device emulator-phone
- name: Upload Coverage Report
uses: codecov/codecov-action@v4
with:
file: ./coverage/lcov.info🚀 每次 PR 自动运行测试,阻断低质量代码合入。
// 在测试环境中替换 DSoftBus 实现
class MockDSoftBus extends DSoftBus {
@override
Future<void> sendCommand(String deviceId, String cmd) async {
if (deviceId == 'faulty_device') {
throw NetworkException('DSoftBus timeout');
}
// 正常逻辑
}
}
// 测试异常处理
test('should show error toast on network failure', () {
final manager = DeviceManager(bridge: MockDSoftBus());
manager.toggleDevice('faulty_device');
expect(toastMessage, '设备无响应,请检查网络');
});💥 主动制造故障,验证应用健壮性。
测试体系的价值不仅在于“发现问题”,更在于 推动架构解耦、接口清晰、行为可预测。通过本文构建的四层测试模型,团队可在 OpenHarmony + Flutter 项目中实现:
下一步行动:
test/ 目录并编写第一个单元测试;附录:工具与文档