uni-app 项目的 E2E 测试
wxa-runner 运行的是 uni-app 编译出的 mp-weixin 目录,渲染、组件、生命周期都由微信官方基础库完成, 和微信里运行的是同一份产物,不是 uni-app 的 H5 版本。已在 Vue 3 的真实 uni-app 项目上验证。
编译产物在哪
wxa-runner 只认编译产物目录,先确认它在哪里:
| 项目 | 开发(监听构建) | 发行 |
|---|---|---|
| 命令行创建的项目 | npm run dev:mp-weixin → dist/dev/mp-weixin | npm run build:mp-weixin → dist/build/mp-weixin |
| HBuilderX 创建的项目 | unpackage/dist/dev/mp-weixin |
下文都按命令行创建的项目来写,HBuilderX 的项目换成对应的目录。
在浏览器里运行和调试
先运行 uni-app 的监听构建,再在另一个终端里启动编译产物目录:
# 终端 1:uni-app 的监听构建
npm run dev:mp-weixin
# 终端 2
npx wxa-runner dev ./dist/dev/mp-weixin --open改了源码后 uni-app 重新构建,wxa-runner 自动热更新。uni-app 的页面用 Component() 构造,修改页面的 JS 后只重新挂载这一页, 页面栈、globalData、Pinia 等全局状态都保留,见热更新。
调试方法和原生小程序一样,见快速开始。
setup 文件放在源码目录
dist 目录由 uni-app 生成,重新构建时可能被清空,所以 setup 文件放在源码根目录,启动时用 --setup 指定:
npx wxa-runner dev ./dist/dev/mp-weixin --setup ./wxa.setup.ts写 E2E 测试
1. 安装
npm i -D @playwright/test @open-wxa/wxa-runner-playwright用例在本机安装的 Google Chrome 里运行。没装 Chrome 时,运行 npx playwright install chrome。
2. 在源码根目录新建 playwright.config.ts
// playwright.config.ts
import { defineConfig } from '@playwright/test';
import type { WxaOptions } from '@open-wxa/wxa-runner-playwright';
export default defineConfig<WxaOptions>({
testDir: 'e2e',
use: {
channel: 'chrome',
// 编译产物目录,相对这个配置文件
wxaProject: './dist/build/mp-weixin',
// 没有 setup 文件时删掉这一行
wxaServerOptions: { setup: './wxa.setup.ts' }
}
});3. 写第一个用例
// e2e/index.spec.ts
import { test, expect } from '@open-wxa/wxa-runner-playwright';
test('首页能打开', async ({ miniProgram }) => {
await miniProgram.open('pages/index/index');
// 换成你首页上的文字
await expect(miniProgram.current.getByText('Hello')).toBeVisible();
});页面路径和 pages.json 里写的一样。
4. 先构建,再运行
在 package.json 里加一个脚本,每次测试前重新构建:
{
"scripts": {
"test:e2e": "npm run build:mp-weixin && playwright test"
}
}npm run test:e2e本地开发时监听构建一直在运行,也可以把 wxaProject 改成 ./dist/dev/mp-weixin,省掉构建这一步。
用例的完整写法(mock 原生 API、拦截请求、断言请求体)见用 Playwright 写微信小程序 E2E 测试。
断言页面上的内容,不要断言页面 data
uni-app(Vue 3)的页面状态在 Vue 实例里(ref、reactive),交给小程序的是编译器生成的渲染数据, 字段名通常是 a、b 这样的短名字,和源码里的变量名不同。所以 toHavePageData、pageData() 读到的不是源码里的状态。
断言时检查页面上的文字和元素,以及跳转和发出的请求:
await miniProgram.current.locator('#submit').click();
await expect(miniProgram).toHavePath('pages/result/result');
await expect(miniProgram.current.getByText('提交成功')).toBeVisible();
const req = await miniProgram.waitForRequest('POST **/api/orders');
expect(req.body).toEqual({ skuId: 1, count: 2 });模板里写的 id、class 编译后保留在页面上,可以直接用作选择器。
在 CI 里运行
CI 里先运行 npm run build:mp-weixin,再运行 npx playwright test,Linux 上不需要开发者工具。 完整的 GitHub Actions 配置见在 CI 里跑小程序 E2E 测试。
限制
- 真实项目上验证过的是 Vue 3 的 uni-app 项目
- 测的是
mp-weixin编译产物,只覆盖微信小程序平台;#ifdef条件编译里其他平台的代码不会运行 - 其他限制和原生小程序一样,见功能与限制

