移动端测试的特殊挑战
移动端测试比 Web 开发更复杂,原因是多方面的:设备碎片化(Android 有数千种设备,iOS 有不同屏幕尺寸)、操作系统版本差异、权限管理(相机、位置、推送等需要用户授权)、网络状态变化、后台/前台切换行为等,都是 Web 开发几乎不需要面对的挑战。
因此移动端测试策略通常分层:单元测试覆盖业务逻辑(快速、稳定);集成测试覆盖组件交互;E2E 测试覆盖关键用户流程(慢但最真实)。
核心名词解释
发布流程总览
单元测试:Jest + Testing Library
// components/__tests__/LikeButton.test.tsx
import { render, screen, fireEvent, waitFor } from '@testing-library/react-native';
import { LikeButton } from '../LikeButton';
// Mock React Query 的 useMutation
const mockMutate = jest.fn();
jest.mock('@tanstack/react-query', () => ({
...jest.requireActual('@tanstack/react-query'),
useMutation: () => ({ mutate: mockMutate, isPending: false }),
}));
describe('LikeButton', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it('显示初始点赞数', () => {
render(<LikeButton postId="p1" initialLikes={42} liked={false} />);
expect(screen.getByText('42')).toBeTruthy();
});
it('点击后调用 like API', async () => {
render(<LikeButton postId="p1" initialLikes={10} liked={false} />);
const button = screen.getByRole('button', { name: /点赞/ });
fireEvent.press(button);
await waitFor(() => {
expect(mockMutate).toHaveBeenCalledWith('p1');
});
});
it('乐观更新:点击后立即显示 +1', () => {
render(<LikeButton postId="p1" initialLikes={10} liked={false} />);
fireEvent.press(screen.getByRole('button'));
// 乐观更新,不等待网络,立即显示 11
expect(screen.getByText('11')).toBeTruthy();
});
it('快照测试', () => {
const { toJSON } = render(
<LikeButton postId="p1" initialLikes={5} liked={true} />
);
expect(toJSON()).toMatchSnapshot();
});
});
EAS Build 配置
// eas.json — EAS Build 配置文件
{
"cli": {
"version": ">= 7.0.0"
},
"build": {
"development": {
"developmentClient": true, // Development Build(支持自定义原生模块)
"distribution": "internal",
"ios": { "simulator": true } // 支持模拟器
},
"preview": {
"distribution": "internal", // 内部分发(TestFlight / 内部测试)
"channel": "preview"
},
"production": {
"distribution": "store", // 应用商店分发
"channel": "production",
"ios": {
"buildConfiguration": "Release"
},
"android": {
"buildType": "app-bundle" // AAB 格式(Google Play 要求)
}
}
},
"submit": {
"production": {
"ios": {
"appleId": "your@apple.com",
"ascAppId": "1234567890"
},
"android": {
"serviceAccountKeyPath": "./google-service-account.json",
"track": "internal" // 先发内部测试轨道
}
}
}
}
OTA 热更新配置
// app.json — expo-updates 配置
{
"expo": {
"updates": {
"url": "https://u.expo.dev/your-project-id",
"checkAutomatically": "ON_LOAD" // 启动时检查更新
},
"runtimeVersion": {
"policy": "sdkVersion" // 根据 SDK 版本决定兼容性
}
}
}
// hooks/useOTA.ts — 手动检查并应用更新
import * as Updates from 'expo-updates';
export function useOTAUpdate() {
useEffect(() => {
async function checkUpdate() {
try {
const update = await Updates.checkForUpdateAsync();
if (update.isAvailable) {
await Updates.fetchUpdateAsync();
// 提示用户重启以应用更新
Alert.alert('发现新版本', '重启应用以应用更新', [
{ text: '稍后', style: 'cancel' },
{
text: '立即重启',
onPress: () => Updates.reloadAsync(),
},
]);
}
} catch (e) {
console.log('OTA 检查失败', e);
}
}
checkUpdate();
}, []);
}
CI/CD:GitHub Actions 自动构建
# .github/workflows/eas-build.yml
name: EAS Build
on:
push:
branches: [main] # main 分支推送自动触发
workflow_dispatch: # 也可以手动触发
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- name: Install dependencies
run: npm ci # --ci 比 install 更严格,使用 lock 文件
- name: Run Jest tests
run: npm test -- --ci # 测试失败则构建停止
- name: Setup EAS
uses: expo/expo-github-action@v8
with:
eas-version: latest
token: ${{ secrets.EXPO_TOKEN }}
- name: Build Preview
run: eas build --platform all --profile preview --non-interactive
eas credentials 命令管理。CI 环境只需要 EXPO_TOKEN 即可,其他凭证 EAS 会自动从服务器获取。
测试与发布的核心要点:① Jest + React Native Testing Library 是单元/集成测试标准组合;用 render() 渲染组件,fireEvent 模拟交互,waitFor 等待异步操作,jest.mock() 替换外部依赖;② Detox 做 E2E 测试时在真机/模拟器上操作,用 element(by.id()).tap() 模拟用户行为,适合关键流程回归;③ EAS Build 在云端构建 IPA/APK,避免本地 Xcode/Android Studio 环境问题;eas build --profile preview 生成测试包,--profile production 生成上架包;④ EAS Submit 自动提交到 App Store Connect 和 Google Play Console;⑤ TestFlight(iOS)和 Internal Testing Track(Android)用于测试人员试用,上架正式版前必须完成测试轮次;⑥ OTA(expo-updates)可以绕过商店审核推送 JS 层更新,但不能更改原生代码;重要 bug fix 的首选方案;⑦ 发版要提前规划:App Store 审核 1-3 个工作日,Google Play 首次上架可能需要 2-7 天。