5.1 KiB
5.1 KiB
app-expo 测试框架规范
目标
测试只解决一件事:阻止高价值回归。
禁止为了覆盖率、形式感或 TDD 仪式感添加低价值测试。
工具链
- 测试框架:
Jest - 组件测试:
@testing-library/react-native - Expo 预设:
jest-expo - E2E:暂不纳入默认门禁,后续如需引入,使用
Maestro
强制规则
- 必须优先测试高风险代码:有分支、有状态、有环境差异、有回归历史。
- 必须优先写用户可见断言,不写实现细节断言。
- 必须把测试文件放在
tests/,禁止放进 Expo Router 的app/目录。 - 必须让
react-test-renderer与react主版本严格一致。 - 必须在新增领域逻辑时评估是否加入
collectCoverageFrom。 - 必须保证 CI 可重复运行,测试不得依赖本地手工环境。
禁止规则
- 禁止为了凑覆盖率给低价值代码补测试。
- 禁止批量给
src/components/ui/*生成型 wrapper 补测试。 - 禁止测试
className、样式细节、第三方库内部实现。 - 禁止默认使用 snapshot。
- 禁止在没有明确回归风险时盲目 TDD。
- 禁止在 CI 中自动更新 snapshot。
测什么
优先级从高到低:
- 纯逻辑和桥接层
- 关键页面的关键可见结果
- 少量高价值主流程
当前门禁覆盖文件:
src/i18n/index.tssrc/constants/theme-bridge.tssrc/app/index.tsx
不测什么
默认不测以下内容,除非出现真实回归或明确业务风险:
src/components/ui/*- 纯透传组件
- 静态文案和静态布局
- 样式实现细节
- 第三方库已经保证的行为
RNTL 规则
- 当前使用
@testing-library/react-native@13 - 直接使用内置 matcher,例如
toBeOnTheScreen() - 不添加
@testing-library/react-native/extend-expect - 不引入
@testing-library/jest-native,除非现有 matcher 明确不够用
TDD 规则
- 新增业务逻辑、修 bug、有明确回归风险时:优先测试先行
- 配置接入、探索性 UI 调整、低风险文案变更:不强制 TDD
- 如果代码很难测:先拆耦合,再决定是否写测试
Snapshot 规则
默认不用 snapshot。
只有同时满足以下条件才允许:
- 组件稳定
- 共享范围广
- 风险来自整体结构而不是交互
- 评审明确同意
否则一律改写为行为断言。
覆盖率规则
覆盖率是门禁,不是目标。
当前阈值:
branches >= 80functions >= 90lines >= 90statements >= 90
这些阈值只对 collectCoverageFrom 中的高价值文件生效。
新增有分支、状态变化或环境差异的领域逻辑时,评审必须回答一个问题:
这个文件要不要进入 collectCoverageFrom?
本地命令
npm run test
npm run test:changed
npm run test:ci
npm run test:update
本地约束:
- 日常开发优先使用
npm run test或npm run test:changed - 提交前必须至少运行一次
npm run test:ci - 只有明确批准时才运行
npm run test:update
CI 门禁
App Expo Quality 必须执行:
npm cinpm run format:checknpm run lintnpm run test:ci
同仓 PR 额外要求:
- 发布 coverage sticky comment
E2E 规则
E2E 不是默认门禁。
只有满足以下条件才引入:
- 核心用户旅程稳定
- 已明确 smoke flow
- 团队能承担维护成本
引入后也只测关键主路径,不做像素巡检,不做大面积 UI 回归脚本。
前置准备
安装 Maestro CLI:
curl -Ls "https://get.maestro.mobile.dev" | bash
构建并安装到目标 iOS Simulator / Android Emulator / 真机。不同 flow 对构建方式的要求不同:
| 场景 | 构建命令 | 读取配置 |
|---|---|---|
| 普通开发 | pnpm ios / pnpm android |
env/development |
| 需要登录态的 E2E | pnpm ios:e2e / pnpm android:e2e |
.env.e2e(staging backend + E2E 开关) |
正常 staging 构建继续使用 env/staging(use-env staging),不注入 EXPO_PUBLIC_E2E。
现有 flow
| Flow 文件 | 用途 | 需要后端 | 需要 E2E 构建 |
|---|---|---|---|
login-smoke.yaml |
登录页协议拦截 smoke,验证 App 启动到未登录态 | 否 | 否 |
login-authenticated.yaml |
快捷登录进入已登录态 | 是 | 是 |
post-login-tabs-smoke.yaml |
登录后 Tab 导航 smoke(对话 → 回忆录 → 我的 → 对话) | 是 | 是 |
post-login-long-chat.yaml |
登录后发送大量对话消息,为回忆录生成提供种子数据 | 是 | 是 |
运行命令
无后端依赖(普通构建即可):
pnpm e2e:ios
pnpm e2e:android
需要 E2E 构建 + 后端 mock 登录:
pnpm e2e:auth:ios
pnpm e2e:auth:android
pnpm e2e:post-login:ios
pnpm e2e:long-chat:ios
调试时可通过 pnpm start:e2e 启动 dev server 并自动加载 .env.e2e。
登录后 E2E 环境要求
- 后端:
APP_ENV不能是production,并开启MOCK_SMS_LOGIN_ENABLED=1 - App:通过
pnpm ios:e2e/pnpm android:e2e构建安装,读取.env.e2e - 所有需要登录态的 flow 通过点击
login.e2e.quickLogin.button进入已登录态