渐进式编程课
鸿蒙 目录
第 24 课2026.08.05

适用场景:同一个函数需要验证多组边界值,而每组测试的执行步骤和断言结构相同

第 24 课:Hypium 数据表驱动测试

  • 日期:2026-08-05
  • 课程序号:第 24 课
  • 知识点:用测试数据表覆盖多组输入与期望输出
  • 适用场景:同一个函数需要验证多组边界值,而每组测试的执行步骤和断言结构相同

承接上一课:生命周期钩子解决测试资源的准备与隔离;本课进一步减少重复的用例代码,让一张数据表驱动同一条业务规则的多组验证。

核心概念

把“输入”和“期望结果”放进测试数据表,然后在一个 it 中逐项执行相同断言:

  • 数据表描述测试条件,不包含业务实现。
  • 每一项都应带有可读的 name,断言失败时能定位具体场景。
  • 数据表驱动适合验证同一条规则;不同业务行为仍应拆成不同的 it。

最小 ArkTS 示例

ts
import { describe, expect, it } from '@ohos/hypium';

interface FormatCase {
  name: string;
  input: number;
  expected: string;
}

function formatUnreadCount(count: number): string {
  if (count <= 0) {
    return '';
  }
  if (count > 99) {
    return '99+';
  }
  return `${count}`;
}

export default function unreadCountTest(): void {
  describe('formatUnreadCount', () => {
    it('formatsDifferentCounts', 0, () => {
      const cases: FormatCase[] = [
        { name: 'zero', input: 0, expected: '' },
        { name: 'normal', input: 8, expected: '8' },
        { name: 'upperBoundary', input: 99, expected: '99' },
        { name: 'overLimit', input: 100, expected: '99+' }
      ];

      cases.forEach((testCase: FormatCase) => {
        const actual: string = formatUnreadCount(testCase.input);
        expect(`${testCase.name}:${actual}`).assertEqual(
          `${testCase.name}:${testCase.expected}`
        );
      });
    });
  });
}

断言把 name 拼进实际值和期望值。若某组失败,输出中会带上场景名,便于快速找到对应数据。

3~5 分钟练习

为数据表补充两组边界输入:-1 应返回空字符串,1 应返回 1。然后判断是否需要修改 formatUnreadCount()。

参考答案

ts
const cases: FormatCase[] = [
  { name: 'negative', input: -1, expected: '' },
  { name: 'one', input: 1, expected: '1' },
  { name: 'zero', input: 0, expected: '' },
  { name: 'normal', input: 8, expected: '8' },
  { name: 'upperBoundary', input: 99, expected: '99' },
  { name: 'overLimit', input: 100, expected: '99+' }
];

现有实现已经满足这两组输入,无需修改业务代码。新增数据行后重新运行测试即可验证边界行为。

与上一课的联系

上一课用套件级和每用例级钩子管理测试环境;本课关注同一业务规则的多组输入覆盖。以后若数据表依赖只读配置,可在 beforeAll 中准备配置,但每组测试数据仍应保持不可变、互不影响。