跳到正文

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-weixinnpm run build:mp-weixin → dist/build/mp-weixin
HBuilderX 创建的项目unpackage/dist/dev/mp-weixin

下文都按命令行创建的项目来写,HBuilderX 的项目换成对应的目录。

在浏览器里运行和调试 ​

先运行 uni-app 的监听构建,再在另一个终端里启动编译产物目录:

bash
# 终端 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 指定:

bash
npx wxa-runner dev ./dist/dev/mp-weixin --setup ./wxa.setup.ts

写 E2E 测试 ​

1. 安装

bash
npm i -D @playwright/test @open-wxa/wxa-runner-playwright

用例在本机安装的 Google Chrome 里运行。没装 Chrome 时,运行 npx playwright install chrome。

2. 在源码根目录新建 playwright.config.ts

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. 写第一个用例

ts
// 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 里加一个脚本,每次测试前重新构建:

json
{
  "scripts": {
    "test:e2e": "npm run build:mp-weixin && playwright test"
  }
}
bash
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() 读到的不是源码里的状态。

断言时检查页面上的文字和元素,以及跳转和发出的请求:

ts
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 条件编译里其他平台的代码不会运行
  • 其他限制和原生小程序一样,见功能与限制

基于 MIT 许可发布。内置基础库是微信官方代码,版权归腾讯所有