🎉 欢迎使用 AI合租 文档系统!返回主站 →
文档中心
💻 Vibe Coding
Day 10: 测试驱动

Day 10: 测试驱动

编写测试保证代码质量,让重构更安全、发布更自信。

测试基础概念

测试金字塔

你:解释一下测试金字塔,什么时候写单元测试、集成测试、E2E测试

测试层级(从下到上):

  • 单元测试:测试单个函数/组件
  • 集成测试:测试模块间交互
  • E2E测试:测试完整用户流程

测试驱动开发(TDD)

你:用 TDD 方式开发一个计算器函数

TDD 流程:

  1. 写测试(红色)
  2. 写代码让测试通过(绿色)
  3. 重构代码(重构)

单元测试

React 组件测试

你:为 Button 组件写单元测试,测试点击事件和不同状态
import { render, fireEvent, screen } from '@testing-library/react';
import Button from './Button';
 
test('按钮点击事件', () => {
  const handleClick = jest.fn();
  render(<Button onClick={handleClick}>点击我</Button>);
 
  fireEvent.click(screen.getByText('点击我'));
  expect(handleClick).toHaveBeenCalledTimes(1);
});
 
test('禁用状态', () => {
  render(<Button disabled>禁用按钮</Button>);
  expect(screen.getByRole('button')).toBeDisabled();
});

工具函数测试

你:为日期格式化函数写测试,覆盖各种输入情况

Mock 数据和函数

你:测试用户登录函数,Mock 掉 API 调用

集成测试

API 测试

你:为用户注册 API 写集成测试,包含成功和失败场景
const request = require('supertest');
const app = require('../app');
 
describe('用户注册 API', () => {
  test('注册成功', async () => {
    const response = await request(app)
      .post('/api/users/register')
      .send({
        email: 'test@example.com',
        password: 'password123',
        name: '测试用户'
      });
 
    expect(response.status).toBe(201);
    expect(response.body.user.email).toBe('test@example.com');
  });
 
  test('邮箱重复注册', async () => {
    await request(app)
      .post('/api/users/register')
      .send({
        email: 'duplicate@example.com',
        password: 'password123',
        name: '用户1'
      });
 
    const response = await request(app)
      .post('/api/users/register')
      .send({
        email: 'duplicate@example.com',
        password: 'password456',
        name: '用户2'
      });
 
    expect(response.status).toBe(409);
    expect(response.body.error).toContain('邮箱已存在');
  });
});

数据库测试

你:测试用户 CRUD 操作,每个测试前后清理数据库

E2E 测试

Playwright 测试

你:用 Playwright 测试完整的用户注册登录流程
const { test, expect } = require('@playwright/test');
 
test('用户注册登录流程', async ({ page }) => {
  // 访问注册页面
  await page.goto('/register');
 
  // 填写注册表单
  await page.fill('input[name="email"]', 'test@example.com');
  await page.fill('input[name="password"]', 'password123');
  await page.fill('input[name="name"]', '测试用户');
 
  // 点击注册按钮
  await page.click('button[type="submit"]');
 
  // 验证跳转到登录页
  await expect(page).toHaveURL('/login');
 
  // 登录
  await page.fill('input[name="email"]', 'test@example.com');
  await page.fill('input[name="password"]', 'password123');
  await page.click('button[type="submit"]');
 
  // 验证登录成功
  await expect(page.locator('.welcome-message')).toContainText('欢迎,测试用户');
});

页面截图对比

你:添加视觉回归测试,对比页面截图发现 UI 变化

测试配置

Jest 配置

你:配置 Jest 测试环境,支持 ES6 模块和 React 组件测试

测试覆盖率

你:配置测试覆盖率报告,要求覆盖率达到 80%

测试数据管理

你:创建测试数据工厂,生成各种测试用的用户数据

常见测试场景

表单验证测试

你:测试登录表单的各种验证规则
  • 邮箱格式验证
  • 密码长度验证
  • 必填字段验证
  • 提交按钮状态

异步操作测试

你:测试数据获取组件的加载、成功、错误状态

权限测试

你:测试不同用户角色的页面访问权限

支付流程测试

你:测试完整的订单支付流程,包含各种异常情况

测试工具选择

前端测试工具

  • Jest:JavaScript 测试框架
  • React Testing Library:React 组件测试
  • Playwright:E2E 测试
  • Storybook:组件测试和文档

后端测试工具

  • Jest:单元测试
  • Supertest:API 测试
  • Sinon:Mock 和 Stub
  • Artillery:性能测试

测试最佳实践

测试命名

// ❌ 不好的测试名
test('test user function', () => {});
 
// ✅ 好的测试名
test('用户登录失败时显示错误信息', () => {});

测试结构

// AAA 模式:Arrange, Act, Assert
test('计算总价包含税费', () => {
  // Arrange - 准备数据
  const items = [{ price: 100 }, { price: 200 }];
  const taxRate = 0.1;
 
  // Act - 执行操作
  const total = calculateTotal(items, taxRate);
 
  // Assert - 断言结果
  expect(total).toBe(330);
});

测试隔离

你:确保每个测试相互独立,不依赖其他测试的结果

测试驱动开发实战

开发新功能

你:用 TDD 开发一个购物车功能

步骤:

  1. 写测试:添加商品到购物车
  2. 写代码:实现添加功能
  3. 重构:优化代码结构
  4. 写测试:删除购物车商品
  5. 写代码:实现删除功能
  6. 重构:继续优化

Bug 修复

你:先写测试重现 bug,然后修复让测试通过

持续集成测试

GitHub Actions

你:配置 CI 流水线,每次 Push 代码自动运行测试
name: Tests
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Setup Node.js
        uses: actions/setup-node@v2
        with:
          node-version: '18'
      - run: npm install
      - run: npm test
      - run: npm run test:e2e

测试结果通知

你:测试失败时自动发送邮件通知团队

性能测试

压力测试

你:测试 API 在高并发下的表现,找出性能瓶颈

内存泄漏测试

你:检查长时间运行的程序是否有内存泄漏

测试理念:测试不是为了证明程序没有 bug,而是为了快速发现 bug。好的测试是最好的文档。

第十天完成! 你已经学会用测试保证代码质量了。明天学习部署上线。

下一步

Day 11: 部署上线 - 将应用部署到生产环境


练习建议

  • 为现有项目添加测试,体验测试带来的安全感
  • 试试 TDD 开发一个小功能
  • 配置测试覆盖率,看看哪些代码没有测试到