简体中文
随着uni-app (x)项目功能的日益复杂,如何保证跨端体验的一致性和高质量,成了一个巨大的挑战。自动化测试是解决这一问题的金钥匙,但编写和维护测试用例本身就是一项耗时耗力的工作。
现在,我们可以借助强大的 AI 编程助手(如 Google Gemini CLI 、Github Copilot CLI、claude-code、qoder cli),将这一过程变得前所未有的简单和高效。本文将一步步教你如何利用 AI,为你的 uni-app 项目自动编写测试用例并运行测试。
在AI CLI中,运行自动化测试,需要在项目目录下,安装 @dcloudio/hbuilderx-cli 依赖包,它让您可以通过 npm scripts 轻松使用 HBuilderX 的各种功能。
# 如果项目下不存在package.json文件,请先运行npm init -y命令,生成package.json文件。
npm init -y
# 安装
npm install @dcloudio/hbuilderx-cli --save-dev
浏览器访问DCloud插件市场,下载插件HBuilderX uni-app自动化测试。
点击【导入插件】,会自动拉起本地安装的HBuilderX,完成插件安装。
uniapp自动化测试环境,需要安装jest、adbkit、puppeteer、playwright等库,安装相关依赖之后,才可以正常使用此插件。
受网络环境、电脑环境、安装包体积大小等,可能安装很慢。
| 平台 | 描述 |
|---|---|
| Web | Chrome、Safari、Firefox |
| 微信小程序 | |
| Android | 支持Android真机、模拟器 |
| iOS | 不支持windows;仅支持在Mac上测试,且仅支持iOS模拟器 |
| Harmony | 支持鸿蒙真机、模拟器 |
注意:
npm包 @dcloudio/hbuilderx-cli,是一个便捷的 HBuilderX 命令行工具包装器,让您可以通过 npm scripts 轻松使用 HBuilderX 的各种功能,也方便AI调取运行日志自动修复问题。
npm包,封装了HBuilderX cli uni-app (x)项目启动、日志查看、自动化测试相关功能。HBuilderX cli文档 、HBuilderX自动化测试插件cli文档
下面将介绍@dcloudio/hbuilderx-cli,使用npm命令运行自动化测试。
特别注意事项:运行测试前,请先确保
HBuilderX uni-app自动化测试插件可以在HBuilderX内正常使用。
# 运行所有测试用例
npm run test:mp-weixin
# 指定测试用例
npm run test:mp-weixin -- --testcaseFile pages/index/index.test.js
# 运行测试到web(默认为 Chrome),运行所有测试用例
npm run test:web
# 运行测试到web特定浏览器、并指定测试用例
npm run test:web -- --browser Chrome --testcaseFile pages/index/index.test.js
npm run test:web -- --browser Safari --testcaseFile pages/index/index.test.js
npm run test:web -- --browser Firefox --testcaseFile pages/index/index.test.js
# iOS模拟器 测试 (默认使用查找到的第一个iOS模拟器设备)
npm run test:app-ios
# iOS模拟器 测试 ,指定设备ID
npm run test:app-ios -- --device_id 3FFE4F41-997F-4ED3-AC3B-DF4ADB9A4262
# iOS模拟器 测试 (默认使用查找到的第一个iOS模拟器设备)
npm run test:app-harmony
# iOS模拟器 测试 ,指定设备ID
npm run test:app-harmony -- --device_id 23EGK24530000100
# Android 测试 (默认使用查找到的第一个android设备)
npm run test:app-android
# Android 测试,指定特定设备
npm run test:app-android -- --device_id emulator-5554
运行到Android,npm run test:app-android 输出结果示例:
> tmp@1.0.0 test:app-android
> uni-test app-android
16:28:04.769 欢迎使用 HBuilderX CLI uni-app (x) 自动化测试命令行工具 (4.3.1) !
16:28:06.479 [uniapp.test] ....... 开始运行测试 ......
16:28:06.479 [uniapp.test] 测试项目:/Users/hx/Documents/__tmp/tmp
16:28:06.480 [uniapp.test] 测试平台:android
16:28:06.484 [uniapp.test] 开始获取可用的测试设备列表 .....
16:28:06.486 [uniapp.test] 可用的测试设备列表: android:feyhuos8ai89jr4p
16:28:06.495 [uniapp.test] 项目 tmp,开始运行测试 ......
16:28:06.496 [uniapp.test] 测试命令为:/Users/hx/DCloud/dcloud_test/env_run_lib/0.0.4/node_modules/jest/bin/jest.js -i --forceExit --json --outputFile="/Users/hx/Library/Application Support/HBuilder X/hbuilderx-for-uniapp-test/tmp/android/feyhuos8ai89jr4p-2092.json" --env="/Applications/HBuilderX-Dev.app/Contents/HBuilderX/plugins/uniapp-cli/node_modules/@dcloudio/uni-automator/dist/environment.js" --globalTeardown="/Applications/HBuilderX-Dev.app/Contents/HBuilderX/plugins/uniapp-cli/node_modules/@dcloudio/uni-automator/dist/teardown.js"
16:28:08.672 [uniapp.test] Compiling...
16:28:12.117 [uniapp.test] DONE Build complete. Watching for changes...
16:28:12.334 [uniapp.test] <Buffer >
16:28:12.334 [uniapp.test] 准备压缩数据
16:28:12.427 [uniapp.test] 压缩数据完成
16:28:12.471 [uniapp.test] wifi server listening 8000
16:28:12.559 [uniapp.test] http server listening 8001
16:28:12.560 [uniapp.test] 准备启动基座
16:28:12.561 [uniapp.test] 启动基座完成
16:28:12.630 [uniapp.test] null Starting: Intent { cmp=io.dcloud.HBuilder/io.dcloud.debug.PullDebugActivity (has extras) }
16:28:13.672 [uniapp.test] 发送同步资源数据 {"mobile":{},"contents":{"project":{"type":"UniApp","appID":"HBuilder"},"fileInfo":[{"action":"writeFile","sourcePath":"http://127.0.0.1:8001/static/?path=/tmp/1765441692185.zip","name":"1765441692185.zip","fullPackage":true,"firstInstall":true}],"app":{"appID":"HBuilder","customBase":false},"refreashType":"reload"}}
16:28:20.896 [uniapp.test] PASS pages/index/index.test.js (13.561 s)
16:28:20.896 [uniapp.test] test title
16:28:20.896 [uniapp.test] ✓ check page title (102 ms)
16:28:20.899 [uniapp.test] Test Suites: 1 passed, 1 total
16:28:20.899 [uniapp.test] Tests: 1 passed, 1 total
16:28:20.899 [uniapp.test] Time: 13.765 s, estimated 14 s
16:28:20.899 [uniapp.test] Snapshots: 0 total
16:28:20.899 [uniapp.test] Ran all test suites.
16:28:23.903 [uniapp.test] Test results written to: ../../../Library/Application Support/HBuilder X/hbuilderx-for-uniapp-test/tmp/android/feyhuos8ai89jr4p-2092.json
16:28:23.913 [uniapp.test] 测试运行结束。
16:28:23.913 [uniapp.test] 测试报告:/Users/hx/Library/Application Support/HBuilder X/hbuilderx-for-uniapp-test/tmp/android/feyhuos8ai89jr4p-2092.json
16:28:23.919 [uniapp.test] [uniapp.test] 测试用例总计:1,运行通过 1,运行失败 0,运行异常 0
16:28:23.920 [uniapp.test] 测试运行结束。
uni-app 提供了一批API,这些API可以操控uni-app应用,包括运行、跳转页面、触发点击等,并可以获取页面元素状态、进行截图。 uni-app 自动化测试API详情
所以我们要做的,就是让AI分析项目分析页面、根据页面编写测试用例、运行测试用例、执行测试、输出测试报告。
因此我们需要将相关规则(页面分析规则、测试用例编写规范、运行命令等等)整理成一份md文件,然后将md文件放置在项目根目录,以便AI读取。
md 文件编写要注意一些事项
规则要具体、明确、可执行,不要写模糊话术
Copilot cli 安装:Github Copilot CLI
打开终端,进入项目目录,运行命令:
copilot -p "读取文件AGENT-Test-Prompt.md,按照要求生成测试用例并运行测试到android" --allow-all-tools
效果如下:
Copilot cli 安装:Google Gemini CLI
打开终端,进入项目目录,输入命令 gemini。
在gemini中提问,比如按照@AGENT-Test-Prompt.md 生成测试用例并运行测试到android
测试用例需要遵循以下规范:
test('描述', () => { ... }) 或 it('描述', () => { ... })将以下内容保存为 AGENT-Test-Prompt.md,放置在项目根目录。在使用 AI CLI 时,让 AI 读取此文件作为指令。
您可以根据需要,进行修改和扩展。
你是一个专业的 uni-app (x) 自动化测试工程师。你的任务是分析项目页面、编写高质量的自动化测试用例、运行测试并修复失败的用例。
1. 分析指定页面的结构和逻辑。
2. 生成或完善对应的测试用例文件 (*.test.js)。
3. 运行测试并输出结果。
4. 如果测试失败,分析原因并修复代码,直到测试通过。
## Workflow
### 1. 分析页面
uni-app (x)项目页面,在pages目录下,一般以 `.uvue` 或`.vue` 结尾
分析内容包括:
* 页面结构: 识别关键组件 (button, input, list 等) 及其 class/id。
* 交互逻辑: 识别点击事件 (@click)、输入事件等。
* 数据状态: 识别页面绑定的数据变量。
* 预期行为: 这里的业务逻辑是什么?用户操作后应该发生什么?
### 2. 测试框架API
uni-app测试框架,提供的API可以操控uni-app应用,包括`控制跳转到指定页面`、`获取页面数据`、`获取页面元素状态`、`触发元素绑定事件`、`调用 uni 对象上任意接口`、`截图`等;本功能使用到了业内常见的测试库如jest。
你可以从 [测试API文档](https://uniapp.dcloud.net.cn/worktile/auto/api.html)获取相关用法。
### 3. 编写/更新测试用例
* 文件路径: 测试文件应与页面文件同级,命名为 `[page-name].test.js`。
* 检查存在性: 如果文件已存在,请读取内容并在其基础上完善;如果不存在,则创建。
* 编写规范:
- 每个测试用例应相互独立,避免依赖其他测试的执行结果
- 遵守 Jest 语法规范,用法如:`test('描述', () => { ... }) 或 it('描述', () => { ... })`
**代码示例**:
```javascript
describe('pages/login/login', () => {
let page;
beforeAll(async () => {
page = await program.reLaunch('/pages/login/login');
await page.waitFor(1000);
});
it('should display correct title', async () => {
const titleEl = await page.$('.title');
expect(await titleEl.text()).toBe('登录');
});
it('should validate phone number length', async () => {
const input = await page.$('.phone-input');
await input.input('123'); // 模拟输入
const value = await input.value();
expect(value.length).toBe(3);
});
});
```
### 4. 运行测试
* Web Chrome: `npm run test:web`
* Web Safari: `npm run test:web -- --browser Safari`
* Web Firefox: `npm run test:web -- --browser Firefox`
* Android: `npm run test:app-android`
* iOS: `npm run test:app-ios`
* harmony: `npm run test:app-harmony`
* 微信小程序: `npm run test:mp-weixin`
注意:
1. 默认运行所有测试文件。
2. 运行指定测试文件,增加参数 `--testcaseFile <test-file-path>`。示例 `npm run test:app-android -- --testcaseFile pages/index/index.test.js`
3. Android、iOS、harmony测试,默认使用查找到的第一个设备进行测试。指定设备,可使用参数 `--deviceId <device-id>`。示例 `npm run test:app-android -- --deviceId emulator-5554`
4. iOS测试需要在Mac环境下运行,不支持windows,且仅支持iOS模拟器运行。
### 5. 结果分析与修复
* 检查终端输出的测试结果。
* 如果通过: 任务完成。
* 如果失败:
* 读取报错信息。
* 分析是测试代码问题还是业务代码问题。
* 修改 `*.test.js` 或业务代码。
* 重新运行测试,直到通过。
## Constraints
* 不要修改非目标页面的代码。
* 保持测试代码简洁、可读。
* 优先使用 `data-testid` 或具体的 class 选择器。
现象: 报错 Port 9520 is in use 或类似端口占用提示。
解决方案:
lsof -i :9520 然后 kill -9 <PID>netstat -ano | findstr 9520 然后 taskkill /PID <PID> /F