HarmonyOS 单元测试——从 LocalUnit.test 到 Ability.test

在这里插入图片描述

一、测试在项目中的地位

在 11 模块架构的英语学习 App 中,测试是保障代码质量的关键手段。每个模块(homePage、topicPage、minePage 以及 commonLib 等)都包含了两种测试目录:src/test/src/ohosTest/

commons/commonLib/
  └── src/
      ├── test/
      │   ├── List.test.ets        # 测试列表入口
      │   └── LocalUnit.test.ets   # 本地单元测试
      ├── ohosTest/
      │   ├── ets/
      │   │   └── test/
      │   │       ├── Ability.test.ets  # Instrumentation 测试
      │   │       └── List.test.ets     # 测试列表入口
      │   └── module.json5

这两种测试目录代表了 HarmonyOS 中两种不同的测试类型:LocalUnitTestInstrumentationTest(ohosTest)

二、test 目录 vs ohosTest 目录

src/test/ 目录(LocalUnitTest)

  • 运行在本地 JVM 上,不依赖真机或模拟器
  • 只能测试纯 TypeScript/ArkTS 逻辑代码
  • 不能调用 @kit API(如 UI 组件、系统服务)
  • 运行速度快,适合频繁执行

src/ohosTest/ 目录(InstrumentationTest)

  • 运行在真机或模拟器上
  • 可以测试完整的能力调用,包括 UI 组件、系统 API
  • 需要打包安装到设备上运行
  • 运行速度慢,通常作为 CI 流程的一部分

选择原则:纯逻辑测试(如工具函数、模型计算)放在 LocalUnitTest;涉及 UI 渲染、系统 API 的测试放在 ohosTest。

三、LocalUnitTest:纯逻辑测试实践

LocalUnitTest 适合测试 ViewModel 中的计算方法、数据模型的序列化/反序列化、工具函数的正确性。

我们的项目中,LocalUnit.test.ets 文件的内容模板:

import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';

export default function localUnitTest() {
  describe('localUnitTest', () => {
    beforeAll(() => {
      // 在所有测试用例之前执行一次
    });
    beforeEach(() => {
      // 在每个测试用例之前执行
    });
    afterEach(() => {
      // 在每个测试用例之后执行
    });
    afterAll(() => {
      // 在所有测试用例之后执行一次
    });

    it('assertContain', 0, () => {
      let a = 'abc';
      let b = 'b';
      expect(a).assertContain(b);
      expect(a).assertEqual(a);
    });
  });
}

这个模板使用了 @ohos/hypium 测试框架,这是 HarmonyOS 官方提供的轻量级测试框架。它提供了类似于 Jest 的 API 风格:describeitexpect

在实际项目中可以扩展的测试用例

it('WordCard constructor test', 0, () => {
  const card = new WordCard(1, 'apple', '/ˈæpl/', 'n.', '苹果',
    'I eat an apple.', '我吃了一个苹果。');
  expect(card.word).assertEqual('apple');
  expect(card.translation).assertEqual('苹果');
  expect(card.category).assertEqual('basic');
});

it('PreferenceUtil put and get', 0, () => {
  PreferenceUtil.getInstance('test').put('key', 'value');
  const result = PreferenceUtil.getInstance('test').get('key');
  expect(result).assertEqual('value');
});

需要注意的是,PreferenceUtil 依赖 ContextUtils 和系统 Preferences API,因此严格的本地单元测试无法测试它——这应该放在 ohosTest 中。

四、InstrumentationTest:UI 测试实践

InstrumentationTest 运行在真机或模拟器上,可以测试 UI 组件的创建和交互。

Ability.test.ets 的典型内容:

import { describe, it, expect } from '@ohos/hypium';
import { Driver, ON } from '@ohos.UiTest';

export default function abilityTest() {
  describe('AbilityTest', () => {
    it('test_page_load', 0, async () => {
      // 创建 UI 测试驱动
      let driver = Driver.create();
      await driver.delayMs(1000);
      
      // 查找页面上的文字元素
      let text = await driver.findComponent(ON.text('英语学习'));
      expect(text != null).assertTrue();
    });
  });
}

InstrumentationTest 的核心能力:

  1. UI 组件查找:通过 Driver 查找页面上的组件(按文本、ID、类型)
  2. 模拟用户操作:点击、滑动、输入
  3. 页面跳转验证:验证路由跳转后的页面内容
  4. 状态验证:验证 @State/@Local 变量的变化

五、ohosTest 中的测试组织

每个模块的 ohosTest 目录结构一致:

features/homePage/src/ohosTest/ets/test/
  ├── Ability.test.ets    # 核心测试文件
  └── List.test.ets       # 测试列表,注册所有测试套件

List.test.ets 的作用是汇总所有测试套件:

import abilityTest from './Ability.test';

export function TestList() {
  abilityTest();
}

这样做的好处是:新增测试文件时,只需要在 List.test.ets 中注册即可,module.json5 中配置的入口文件保持不变。

ohosTest 目录下的 module.json5 配置了测试模块的信息:

{
  "module": {
    "name": "homePage_ohosTest",
    "type": "test",
    "srcPath": "",
    "description": "HomePage test module",
    "testRunner": "ohosTestRunner"
  }
}

六、测试策略与覆盖率

在 11 模块架构下,建议的测试策略是:

  1. 核心逻辑全覆盖:commonLib 中的 Manager(PreferenceUtil、NewWordManager、AudioPlayer)和 Utils(Logger、ContextUtils)应该有完整的 LocalUnitTest 覆盖

  2. 关键页面 UI 测试:homePage 的 MainPage、topicPage 的 WordCardPage、minePage 的 MinePage 应该有 InstrumentationTest,验证页面加载和基本交互

  3. 边界情况测试:数据处理函数(如数据序列化、生词本增删改查)需要测试边界情况(空数据、重复数据、大数据量)

  4. 构建集成:在 hvigorfile.ts 中配置运行测试的任务,CI/CD 流水线中自动执行

七、总结

HarmonyOS 的测试体系提供了 LocalUnitTest 和 InstrumentationTest 两种互补的方式。LocalUnitTest(src/test/)负责纯逻辑的快速验证,InstrumentationTest(src/ohosTest/)负责真机环境下的集成测试。在我们的项目中,每个模块都遵循这种双测试目录的结构,为代码质量提供了基础保障。开发者应该根据测试目标选择合适的测试类型,并且保持测试与代码的同步演进。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐