Skip to content

前端自动化测试指南

自动化测试是前端工程化的核心环节,用于保障代码质量、防止回归错误 (Regressions) 并提升重构信心。

1. 测试金字塔与策略

1.1 测试层级

从下到上,成本越来越高,运行速度越来越慢:

  • 单元测试 (Unit Testing):
    • 对象: 独立的函数、类、组件。
    • 特点: 运行快,隔离性强,专注于逻辑正确性。
    • 工具: Jest, Vitest.
  • 集成测试 (Integration Testing):
    • 对象: 多个单元组合在一起的交互(如父子组件交互、Hook 与组件交互)。
    • 特点: 模拟真实环境,性价比最高(Testing Trophy 理念推荐)。
    • 工具: React Testing Library, Vue Test Utils.
  • 端到端测试 (E2E Testing):
    • 对象: 整个应用,模拟真实用户操作(点击、跳转、API请求)。
    • 特点: 环境最真实,但运行慢、维护成本高。
    • 工具: Cypress, Playwright.

1.2 静态分析 (Static Analysis)

在代码运行前通过工具检查潜在错误。

  • ESLint: 检查语法和风格错误。
  • TypeScript: 类型检查,防止类型相关的运行时错误。
  • Prettier: 统一代码格式。

2. 常用测试工具链

2.1 Test Runners (测试运行器)

  • Jest:
    • Facebook 推出,大而全(内置断言、Mock、覆盖率)。
    • 基于 Node.js 环境(JSDOM 模拟浏览器)。
    • React 项目标配。
  • Vitest:
    • 由 Vue/Vite 团队推出。
    • 与 Vite 共享配置,速度极快(ESM Native)。
    • API 兼容 Jest,适合 Vite 项目。

2.2 Component Testing Utilities

  • Testing Library (React/Vue/Angular):
    • 核心理念: "测试你的软件的使用方式,而不是实现细节"。
    • 推荐通过 getByRole, getByText 查找元素,而非 CSS 选择器。
  • Vue Test Utils: Vue 官方的底层测试库。
  • Enzyme: (已过时) Airbnb 推出,允许深层访问组件内部状态,不推荐用于现代 React 测试。

2.3 E2E Tools

  • Cypress:
    • 开发者体验极佳,自带浏览器 GUI,调试方便。
    • 运行在浏览器内部。
  • Playwright:
    • Microsoft 推出,支持所有现代浏览器内核 (Chromium, WebKit, Firefox)。
    • 运行速度快,支持并行,支持多 Tab。

3. 核心概念与技巧

3.1 Mocking (模拟)

  • Mock Function: 捕获函数调用(调用次数、参数)。
  • Mock Module: 模拟第三方库或 API 请求,避免真实网络 IO。
javascript
// Jest/Vitest 示例
import axios from 'axios';
vi.mock('axios'); // 模拟模块

test('API call', async () => {
  axios.get.mockResolvedValue({ data: 'hello' });
  // ...
});

3.2 TDD (测试驱动开发)

  1. Red: 写一个失败的测试。
  2. Green: 写最少量的代码让测试通过。
  3. Refactor: 重构代码,保持测试通过。

3.3 快照测试 (Snapshot Testing)

将组件渲染结果保存为字符串文件。如果不小心改坏了 UI 结构,快照对比会报错。

javascript
expect(component).toMatchSnapshot();

4. 最佳实践 (Testing Library 风格)

  1. 避免测试实现细节:
    • ❌ 不要测试 component.state.count === 1
    • ✅ 应该测试 screen.getByText('Count: 1') 是否存在。
  2. 以用户视角查询元素:
    • 优先: getByRole (button, textbox), getByLabelText, getByPlaceholderText.
    • 最后: querySelector (class, id)。
  3. Mock 尽可能少的边界:
    • 集成测试中尽量使用真实的子组件,而不是全部 Mock 掉。
    • 使用 MSW (Mock Service Worker) 在网络层拦截请求,而不是 Mock axios 库本身。

5. 常见面试题

  • Unit Test 和 E2E Test 的区别是什么?
  • 如何测试一个异步请求?(async/await, waitFor)
  • 什么是 Code Coverage (代码覆盖率)?100% 覆盖率是必须的吗?
  • TDD 和 BDD (行为驱动开发) 的区别?

MIT Licensed | Keep Learning.