第 41 课2026.08.27
适用场景:多个成功或失败用例共用测试结构,但事件记录、失败配置和被测对象会在运行中改变
第 41 课:Hypium 多阶段测试共享夹具与用例隔离
- 日期:2026-08-27
- 课程序号:第 41 课
- 知识点:用
beforeEach重建多阶段测试的可变夹具,保证参数化用例彼此隔离 - 适用场景:多个成功或失败用例共用测试结构,但事件记录、失败配置和被测对象会在运行中改变
承接上一课:上一课建立了多阶段失败矩阵;本课进一步隔离每个矩阵用例的运行状态,避免前一个用例留下的事件影响后一个用例。
核心概念
- 参数表等只读数据可以在套件内共享;事件数组、Fake 配置和被测对象属于可变夹具,应在每个用例前重建。
beforeEach在每个it执行前运行,适合集中创建一套干净的测试环境。- 用例只设置自己的差异条件,例如
failAt,其余准备工作交给共享夹具。 - 用例隔离后,测试结果不依赖执行顺序,单独运行某个用例也应得到相同结果。
最小 ArkTS / Hypium 示例
ts
import { beforeEach, describe, expect, it } from '@ohos/hypium';
interface FailureCase {
name: string;
failAt: string;
expectedEvents: string;
}
class Stage {
constructor(private readonly name: string,
private readonly events: string[]) {}
async run(failAt: string): Promise<void> {
this.events.push(`${this.name}-started`);
if (failAt === this.name) {
throw new Error(`${this.name}失败`);
}
this.events.push(`${this.name}-finished`);
}
}
class PublishController {
constructor(private readonly events: string[]) {}
async publish(failAt: string): Promise<void> {
await new Stage('保存', this.events).run(failAt);
await new Stage('校验', this.events).run(failAt);
await new Stage('上传', this.events).run(failAt);
this.events.push('发布成功');
}
}
const cases: FailureCase[] = [
{
name: '保存失败后停止',
failAt: '保存',
expectedEvents: '保存-started'
},
{
name: '校验失败后停止',
failAt: '校验',
expectedEvents: '保存-started,保存-finished,校验-started'
}
];
export default function isolatedFailureMatrixTest(): void {
describe('isolated failure matrix', () => {
let events: string[] = [];
let controller: PublishController = new PublishController(events);
beforeEach(() => {
events = [];
controller = new PublishController(events);
});
cases.forEach((testCase: FailureCase) => {
it(testCase.name, 0, async () => {
await controller.publish(testCase.failAt).catch(() => {});
expect(events.join(',')).assertEqual(testCase.expectedEvents);
});
});
});
}这里共享的是不会在测试中修改的 cases;events 和 controller 则由 beforeEach 为每个用例重新创建。
3~5 分钟练习
增加一个“全部阶段成功”的用例,并确保它可以放在失败用例之前或之后运行,事件断言都不会受其他用例影响。
参考答案
先在参数表中加入成功场景:
ts
{
name: '全部阶段成功',
failAt: '',
expectedEvents: '保存-started,保存-finished,校验-started,校验-finished,' +
'上传-started,上传-finished,发布成功'
}beforeEach 会在该用例开始前把 events 重置为空数组,并创建引用新数组的 controller。因此无论成功用例排在矩阵中的什么位置,它都只会断言本次执行产生的事件。
与上一课的联系
上一课用参数化矩阵覆盖各阶段失败;本课保留同一矩阵结构,并用 beforeEach 隔离事件记录和被测对象,使各失败场景不受执行顺序影响。