前言

“我改了一行,不知道会不会弄坏别的功能”——这是没测试的噩梦。单元测试就是给代码买保险:你写个小测试,验证"这个函数输入 A 应该输出 B",以后谁改坏了立马红。

HarmonyOS 用 @ohos/hypium 测试框架。这篇文章从零写一个测试,讲清 @Test、断言、怎么跑、怎么看覆盖率。

A hand-drawn doodle illustration on pure white pap

先有一个被测函数

测试的前提是:你要测的代码是"纯函数"或可独立调用的。比如一个工具:

代码实现

// utils/Calc.ets
export function add(a: number, b: number): number {
  return a + b
}
export function isEven(n: number): boolean {
  return n % 2 === 0
}

写测试文件

测试文件一般放在 src/test/ 下,用 describe/it 组织,用 @Test 标注用例:

核心代码

import { describe, it, expect } from '@ohos/hypium'
import { add, isEven } from '../utils/Calc'

export default function calcTest() {
  describe('Calc 测试', () => {
    it('add 两数相加', 0, () => {
      expect(add(1, 2)).assertEqual(3)
    })
    it('isEven 偶数判断', 0, () => {
      expect(isEven(4)).assertEqual(true)
      expect(isEven(3)).assertEqual(false)
    })
  })
}

A hand-drawn doodle illustration on pure white pap

讲解:

  • describe('Calc 测试', ...):测试套件名,分组用。
  • it('用例名', 0, () => {...}):单个测试用例,0 是用例标记位。
  • expect(x).assertEqual(y):断言,x 应该等于 y,不等就测试失败。

断言方法还有 assertTrueassertClose(近似相等)、assertFail 等,按场景选。

怎么跑测试

在 DevEco 里,右键测试文件 → “Run ‘xxxTest’”,或用命令行。跑完会显示每个用例过没过:

完整示例

Calc 测试
  ✓ add 两数相加
  ✓ isEven 偶数判断
2 passed, 0 failed

红的就是要修的。测试的价值就在这一刻:改坏代码,立刻红给你看。

测试异步代码

涉及 Promise 的,用 async/await

代码解析

it('异步请求返回数据', 0, async () => {
  const res = await fetchUser(1)
  expect(res.id).assertEqual(1)
})

A hand-drawn doodle illustration on pure white pap

看覆盖率

覆盖率告诉你"测试覆盖了多少代码行"。DevEco 开启覆盖率后,会标出哪些行没被测到(红色),提示你补用例。

  • 行覆盖率:多少行代码被执行过。
  • 分支覆盖率:if/else 各分支是否都测了。

目标不必 100%,但核心逻辑(计算、校验、状态机)尽量覆盖到。

常见误区(小白必踩)

误区 说明
只测主流程不测边界 add(1,2) 过了就以为没问题,负数、空值、超大数才是容易出错的。
异步不 await 测试 Promise 忘了 async/await,用例直接过但啥也没验。
不看覆盖率 覆盖率告诉你哪些行没测到,红的那几行往往就是 bug 藏身处。

下面这段代码可以直接复制到 DevEco Studio 里运行。建议你边读边敲,改一改文末「动手改一改」里的参数,亲眼看看效果。

完整可运行示例:单元测试

@Test 验证一个纯函数。

实现拆解

// 用 Hypium 写单元测试
import { describe, it, expect } from '@ohos/hypium'

function add(a: number, b: number): number { return a + b }

export default function testSuite() {
  describe('math', () => {
    it('add 应该返回两数之和', 0, () => {
      expect(add(1, 2)).assertEqual(3)
    })
  })
}

你会看到什么:运行测试,Hypium 报告 add(1,2) === 3 通过。把断言改成 assertEqual(4) 会立刻变红,直观体现「测试即文档」。

动手改一改

  • 加一个 it('负数相加') 覆盖边界。
  • expect(x).assertFail() 故意制造失败,看报告样式。
  • 给被测函数加 @Test 标注做模块内联测试。

写在最后

单元测试不是负担,是改代码时的底气。套路就三步:导入被测函数 → 写 it 用例 → expect 断言。从你最易出错的那个工具函数开始写第一个测试,跑通的那一刻,你会觉得"以后敢改代码了"。

建议把项目的"输入校验、金额计算、状态转换"这类核心逻辑都补上测试——它们最该被保护,也最容易被改坏。

Logo

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

更多推荐