geo/docs/03-开发指南/testing.md

3.6 KiB
Raw Permalink Blame History

测试指南

测试策略

测试金字塔

        ┌───────┐
        │  E2E  │     少量端到端测试
       ┌┴───────┴┐
       │ Integration│   API和组件集成测试
      ┌┴──────────┴┐
      │   Unit     │    大量单元测试
     ┌┴────────────┴┐

测试覆盖目标

层级 覆盖率目标
单元测试 80%+
集成测试 60%+
E2E测试 关键流程覆盖

后端测试

目录结构

tests/
├── conftest.py          # pytest配置和fixture
├── unit/               # 单元测试
│   ├── services/
│   └── models/
├── integration/        # 集成测试
│   └── api/
└── fixtures/           # 测试数据

运行测试

# 运行所有测试
pytest

# 运行单元测试
pytest tests/unit/

# 运行集成测试
pytest tests/integration/

# 带覆盖率
pytest --cov=app --cov-report=html

编写单元测试

import pytest
from app.services.user_service import UserService
from app.models import User

@pytest.fixture
def user_service(db_session):
    return UserService(session=db_session)

@pytest.fixture
def sample_user():
    return User(
        id=1,
        email="test@example.com",
        username="testuser"
    )

def test_get_user_by_id(user_service, sample_user, db_session):
    db_session.add(sample_user)
    db_session.commit()
    
    result = user_service.get_user_by_id(1)
    
    assert result is not None
    assert result.email == "test@example.com"

Fixtures

常用Fixturesconftest.py

@pytest.fixture
def db_session():
    """数据库会话"""
    ...

@pytest.fixture
def client():
    """测试客户端"""
    ...

@pytest.fixture
def auth_headers():
    """认证头"""
    ...

前端测试

工具链

  • Vitest - 单元测试
  • React Testing Library - 组件测试
  • Playwright - E2E测试

运行测试

# 单元测试
npm run test

# E2E测试
npm run test:e2e

# 覆盖率
npm run test:coverage

组件测试示例

import { render, screen, userEvent } from '@testing-library/react';
import { Button } from './Button';

describe('Button', () => {
  it('renders with label', () => {
    render(<Button label="Click me" onClick={() => {}} />);
    expect(screen.getByText('Click me')).toBeInTheDocument();
  });

  it('calls onClick when clicked', async () => {
    const onClick = vi.fn();
    render(<Button label="Click me" onClick={onClick} />);
    
    await userEvent.click(screen.getByText('Click me'));
    
    expect(onClick).toHaveBeenCalled();
  });
});

E2E测试

使用Playwright进行端到端测试

import { test, expect } from '@playwright/test';

test.describe('登录流程', () => {
  test('应该能够登录并跳转到dashboard', async ({ page }) => {
    await page.goto('/login');
    
    await page.fill('[name="email"]', 'test@example.com');
    await page.fill('[name="password"]', 'password123');
    await page.click('[type="submit"]');
    
    await expect(page).toHaveURL('/dashboard');
    await expect(page.locator('h1')).toContainText('品牌健康中心');
  });
});

CI集成

测试在每次PR时自动运行

# .github/workflows/test.yml
name: Test

on: [pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run tests
        run: |
          docker-compose up -d
          pytest
          npm run test:e2e