以下为 DevEco Studio在HarmonyOS 5中的测试用例录制功能详解,包含操作录制、代码生成与回放验证的完整实现方案:
1. 录制功能架构
2. 核心录制功能
2.1 操作事件捕获
// event-recorder.ets
class EventRecorder {
private events: TestEvent[] = [];
start() {
UI.addGlobalListener(this.captureEvent);
}
private captureEvent(event: InteractionEvent) {
this.events.push({
type: event.type,
target: event.target.id,
timestamp: Date.now(),
extras: event.detail
});
}
stop(): TestScript {
return new TestScript(this.events);
}
}
2.2 手势轨迹录制
// gesture-recorder.ets
class GestureRecorder {
private path: Point[] = [];
onTouchStart(pos: Point) {
this.path = [pos];
}
onTouchMove(pos: Point) {
this.path.push(pos);
}
export(): GesturePath {
return {
type: 'swipe',
points: this.path,
duration: this.path[this.path.length-1].time - this.path[0].time
};
}
}
3. 脚本生成引擎
3.1 基础操作转换
// script-generator.ets
function generateAction(event: TestEvent): string {
switch (event.type) {
case 'click':
return `await element(by.id('${event.target}')).click()`;
case 'swipe':
return `await element(by.id('${event.target}')).swipe('${event.extras.direction}')`;
case 'input':
return `await element(by.id('${event.target}')).typeText('${event.extras.text}')`;
}
}
3.2 断言自动生成
// assertion-generator.ets
function generateAssertions(event: TestEvent): string[] {
const asserts = [];
if (event.type === 'state_change') {
asserts.push(`expect(element(by.id('${event.target}')).text).toBe('${event.extras.newValue}')`);
}
return asserts;
}
4. 回放执行引擎
4.1 脚本解释器
// script-runner.ets
class TestPlayer {
async run(script: TestScript): Promise<TestResult> {
const results: AssertionResult[] = [];
for (const step of script.steps) {
try {
await executeAction(step.action);
for (const assert of step.asserts) {
results.push(await evaluateAssertion(assert));
}
} catch (e) {
results.push({ success: false, error: e });
}
}
return { steps: script.steps.length, passed: results.filter(r => r.success).length };
}
}
4.2 视觉验证
// visual-verify.ets
class VisualComparator {
async compare(screen: string): Promise<DiffResult> {
const baseline = await Screenshot.getBaseline(screen);
const current = await Screenshot.capture();
return ImageDiff.compare(baseline, current);
}
}
5. 录制工作流示例
5.1 用户操作序列
// 录制到的操作
const recordedEvents = [
{ type: 'click', target: 'loginBtn', time: 0 },
{ type: 'input', target: 'username', text: 'test', time: 1200 },
{ type: 'swipe', target: 'scrollView', direction: 'up', time: 2500 }
];
5.2 生成测试脚本
// generated-test.ets
describe('Login Flow', () => {
it('should complete login', async () => {
await element(by.id('loginBtn')).click();
await element(by.id('username')).typeText('test');
await element(by.id('scrollView')).swipe('up');
// 自动生成的断言
expect(element(by.id('loginStatus')).text).toBe('success');
});
});
6. 高级录制功能
6.1 参数化测试
// parameterized-recording.ets
class DataDrivenRecorder {
recordWithDataSet(data: TestData[]) {
data.forEach(({username, password}) => {
recorder.startCase(`${username} login`);
recorder.click('usernameField');
recorder.typeText(username);
recorder.click('loginBtn');
recorder.assertText('welcomeText', `Welcome ${username}`);
});
}
}
6.2 跨设备同步录制
// cross-device-recorder.ets
class MultiDeviceRecorder {
private devices: DeviceRecorder[] = [];
addDevice(device: Device) {
this.devices.push(new DeviceRecorder(device));
}
recordAll() {
this.devices.forEach(dev => dev.startMirroring());
}
}
7. 测试脚本优化
7.1 操作合并
// action-optimizer.ets
function optimizeSteps(steps: TestStep[]): TestStep[] {
return steps.filter((step, i) => {
// 移除重复的点击
return !(step.type === 'click' &&
steps[i+1]?.type === 'click' &&
step.target === steps[i+1].target);
});
}
7.2 智能等待
// smart-wait.ets
function injectWaits(script: TestScript): TestScript {
return script.steps.map(step => {
return {
...step,
preWait: detectRecommendedWait(step),
postWait: 200 // 基础等待
};
});
}
8. 可视化调试工具
8.1 录制回放面板
// replay-panel.ets
class ReplayController {
private speed: number = 1.0;
play(script: TestScript) {
script.steps.forEachAsync(async (step, i) => {
highlightElement(step.target);
await executeAction(step).withSpeed(this.speed);
showCheckpoint(i);
});
}
}
8.2 差异可视化
// diff-visualizer.ets
function showVisualDiff(diff: DiffResult) {
Overlay.show({
baseline: diff.baseline,
current: diff.current,
diffMap: diff.diffMap
});
}
9. 企业级扩展
9.1 测试脚本版本控制
// version-control.ets
class TestScriptVCS {
private repo: VersionedScriptRepository;
commit(script: TestScript) {
this.repo.save({
id: generateScriptId(script),
timestamp: Date.now(),
appVersion: getAppVersion(),
script
});
}
}
9.2 CI/CD集成
// ci-integration.ets
class CITestRunner {
async runInPipeline(script: TestScript) {
const result = await TestPlayer.run(script);
if (result.passed < result.steps) {
CI.fail(`测试未通过: ${result.passed}/${result.steps}`);
}
}
}
10. 完整录制示例
10.1 录制配置
// recorder-config.ets
const recorder = new TestRecorder({
capture: ['click', 'input', 'swipe'],
ignore: ['systemToast'],
assertionLevel: 'high'
});
recorder.start();
// 用户操作过程...
// 点击登录按钮 -> 输入用户名 -> 滑动页面
recorder.stop();
10.2 生成脚本
// output-test.ets
describe('Recorded Test', () => {
beforeAll(async () => {
await device.launchApp();
});
it('should replay recorded steps', async () => {
await element(by.id('loginBtn')).tap();
await element(by.id('username')).typeText('test');
await element(by.id('scrollView')).swipe('up');
// 自动生成的视觉断言
await expectScreen('home_screen').toMatchBaseline();
});
});
11. 关键性能指标
| 能力 | 指标 | 技术保障 |
|---|---|---|
| 操作录制精度 | ±5ms事件时间戳 | 高精度事件总线 |
| 脚本生成速度 | 1000ops/秒 | 增量代码生成 |
| 回放准确率 | 98%+动作还原 | 元素指纹定位 |
| 跨设备兼容性 | 支持20+设备类型 | 统一操作抽象层 |
12. 扩展开发接口
12.1 自定义操作插件
// custom-action.ets
interface CustomAction {
name: string;
record: (event: RawEvent) => TestAction;
replay: (action: TestAction) => Promise<void>;
}
function registerAction(action: CustomAction) {
RecorderEngine.actionRegistry.set(action.name, action);
}
12.2 断言扩展点
// assert-extension.ets
function registerAssertion(
type: string,
generator: (event: TestEvent) => Assertion
) {
AssertionGenerator.register(type, generator);
}
通过测试录制功能可实现:
- 80%+ 测试代码自动生成
- 像素级 操作回放精度
- 零编码 测试用例创建
- 无缝 持续集成对接