Files
novalon-website/docs/plans/2026-03-10-gradual-coverage-improvement.md
T

12 KiB
Raw Blame History

渐进式测试覆盖率提升计划

For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

Goal: 建立可持续的测试覆盖率提升体系,从当前29.5%逐步提升到更高水平,同时保证开发效率和代码质量。

Architecture: 采用分层覆盖率策略,核心业务逻辑层高覆盖(70-80%),UI组件层中覆盖(60-70%),页面展示层适度覆盖(40-50%)。

Tech Stack: Jest, React Testing Library, Next.js, TypeScript, GitHub Actions


已完成任务

Task 1: 调整Jest配置覆盖率阈值

Files:

  • Modify: jest.config.js:12-18

Step 1: 修改覆盖率阈值为合理水平

coverageThreshold: {
  global: {
    branches: 20,
    functions: 25,
    lines: 25,
    statements: 25,
  },
},

Step 2: 运行测试验证配置

Run: npm run test:unit -- --coverage --coverageReporters=text-summary

Expected: PASS with coverage above 25%

Step 3: 提交配置修改

git add jest.config.js
git commit -m "test: adjust coverage threshold to reasonable level (25%)"

第一阶段:稳定当前覆盖率(1-2周)

Task 2: 补充核心业务逻辑测试

Files:

  • Create: src/lib/auth/session.test.ts
  • Create: src/lib/auth/token.test.ts
  • Create: src/lib/validation.test.ts

Step 1: 为session管理编写测试

describe('session management', () => {
  it('should create session with user data', () => {
    const session = createSession({ userId: '123', role: 'admin' });
    expect(session).toBeDefined();
    expect(session.userId).toBe('123');
  });

  it('should validate session expiration', () => {
    const expiredSession = createSession({ userId: '123', expiresIn: -1 });
    expect(isSessionValid(expiredSession)).toBe(false);
  });
});

Step 2: 运行测试验证失败

Run: npm run test:unit -- --testPathPattern="session.test.ts"

Expected: FAIL with "createSession not defined"

Step 3: 实现session管理功能

export function createSession(userData: SessionData): Session {
  return {
    ...userData,
    createdAt: Date.now(),
    expiresAt: Date.now() + (24 * 60 * 60 * 1000), // 24小时
  };
}

export function isSessionValid(session: Session): boolean {
  return Date.now() < session.expiresAt;
}

Step 4: 运行测试验证通过

Run: npm run test:unit -- --testPathPattern="session.test.ts"

Expected: PASS

Step 5: 提交

git add src/lib/auth/session.test.ts src/lib/auth/session.ts
git commit -m "test: add session management tests"

Task 3: 补充数据验证测试

Files:

  • Create: src/lib/validation.test.ts
  • Modify: src/lib/validation.ts

Step 1: 编写数据验证测试

describe('validation', () => {
  describe('email validation', () => {
    it('should accept valid email', () => {
      expect(validateEmail('test@example.com')).toBe(true);
    });

    it('should reject invalid email', () => {
      expect(validateEmail('invalid')).toBe(false);
    });
  });

  describe('phone validation', () => {
    it('should accept valid phone', () => {
      expect(validatePhone('13800138000')).toBe(true);
    });

    it('should reject invalid phone', () => {
      expect(validatePhone('123')).toBe(false);
    });
  });
});

Step 2: 运行测试验证失败

Run: npm run test:unit -- --testPathPattern="validation.test.ts"

Expected: FAIL with validation functions not defined

Step 3: 实现验证函数

export function validateEmail(email: string): boolean {
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  return emailRegex.test(email);
}

export function validatePhone(phone: string): boolean {
  const phoneRegex = /^1[3-9]\d{9}$/;
  return phoneRegex.test(phone);
}

Step 4: 运行测试验证通过

Run: npm run test:unit -- --testPathPattern="validation.test.ts"

Expected: PASS

Step 5: 提交

git add src/lib/validation.test.ts src/lib/validation.ts
git commit -m "test: add data validation tests"

Task 4: 优化测试执行性能

Files:

  • Modify: jest.config.js
  • Create: .github/workflows/test-optimized.yml

Step 1: 配置并行测试执行

// jest.config.js
module.exports = {
  // ... existing config
  maxWorkers: '50%',
};

Step 2: 创建优化后的CI工作流

# .github/workflows/test-optimized.yml
name: Optimized Test

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        shard: [1, 2, 3, 4]

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Run tests (shard ${{ matrix.shard }})
        run: npm run test:unit -- --shard=${{ matrix.shard }}/4

      - name: Upload coverage
        if: matrix.shard == 4
        uses: codecov/codecov-action@v4

Step 3: 提交配置

git add jest.config.js .github/workflows/test-optimized.yml
git commit -m "ci: optimize test execution with parallelization"

第二阶段:提升覆盖率到35%(1-2个月)

Task 5: 补充API路由测试

Files:

  • Create: src/app/api/contact/route.test.ts
  • Create: src/app/api/auth/route.test.ts

Step 1: 编写API路由测试

describe('/api/contact', () => {
  it('should handle POST request', async () => {
    const response = await POST(new Request('http://localhost/api/contact', {
      method: 'POST',
      body: JSON.stringify({ name: 'Test', email: 'test@example.com' }),
    }));

    expect(response.status).toBe(200);
  });

  it('should validate required fields', async () => {
    const response = await POST(new Request('http://localhost/api/contact', {
      method: 'POST',
      body: JSON.stringify({}),
    }));

    expect(response.status).toBe(400);
  });
});

Step 2: 运行测试验证失败

Run: npm run test:unit -- --testPathPattern="api/contact/route.test.ts"

Expected: FAIL with API route not tested

Step 3: 实现API路由验证逻辑

// 确保API路由有适当的验证和错误处理
export async function POST(request: Request) {
  try {
    const body = await request.json();

    if (!body.name || !body.email) {
      return Response.json({ error: 'Missing required fields' }, { status: 400 });
    }

    // 处理逻辑...
    return Response.json({ success: true }, { status: 200 });
  } catch (error) {
    return Response.json({ error: 'Internal server error' }, { status: 500 });
  }
}

Step 4: 运行测试验证通过

Run: npm run test:unit -- --testPathPattern="api/contact/route.test.ts"

Expected: PASS

Step 5: 提交

git add src/app/api/contact/route.test.ts src/app/api/contact/route.ts
git commit -m "test: add API route tests"

Task 6: 补充数据库操作测试

Files:

  • Create: src/db/queries.test.ts
  • Create: src/db/mutations.test.ts

Step 1: 编写数据库查询测试

describe('database queries', () => {
  it('should query user by id', async () => {
    const user = await getUserById('123');
    expect(user).toBeDefined();
    expect(user.id).toBe('123');
  });

  it('should return null for non-existent user', async () => {
    const user = await getUserById('non-existent');
    expect(user).toBeNull();
  });
});

Step 2: 运行测试验证失败

Run: npm run test:unit -- --testPathPattern="db/queries.test.ts"

Expected: FAIL with database functions not tested

Step 3: 实现数据库查询函数

export async function getUserById(id: string): Promise<User | null> {
  const result = await db.select().from(users).where(eq(users.id, id)).limit(1);
  return result[0] || null;
}

Step 4: 运行测试验证通过

Run: npm run test:unit -- --testPathPattern="db/queries.test.ts"

Expected: PASS

Step 5: 提交

git add src/db/queries.test.ts src/db/queries.ts
git commit -m "test: add database query tests"

Task 7: 提升分支覆盖率

Files:

  • Modify: src/lib/auth/permissions.test.ts
  • Modify: src/lib/upload.test.ts

Step 1: 添加边界条件测试

describe('permissions edge cases', () => {
  it('should handle null role', () => {
    expect(hasPermission(null, 'content', 'read')).toBe(false);
  });

  it('should handle undefined resource', () => {
    expect(hasPermission('admin', undefined, 'read')).toBe(false);
  });

  it('should handle empty action string', () => {
    expect(hasPermission('admin', 'content', '')).toBe(false);
  });
});

Step 2: 运行测试验证通过

Run: npm run test:unit -- --testPathPattern="permissions.test.ts"

Expected: PASS with improved branch coverage

Step 3: 提交

git add src/lib/auth/permissions.test.ts
git commit -m "test: improve branch coverage with edge cases"

第三阶段:建立测试质量体系(2-3个月)

Task 8: 创建测试指南文档

Files:

  • Create: docs/testing-guide.md

Step 1: 编写测试指南

# 测试指南

## 测试策略

本项目采用分层覆盖率策略:
- 核心业务逻辑层:70-80%覆盖率
- UI组件层:60-70%覆盖率
- 页面展示层:40-50%覆盖率

## 测试编写规范

### 单元测试
- 使用Jest和React Testing Library
- 遵循AAA模式(Arrange-Act-Assert
- 每个测试只验证一个行为

### 集成测试
- 测试组件间的交互
- 使用真实的数据流
- 避免过度mock

## 常见问题

**Q: 如何处理异步测试?**
A: 使用async/await和waitFor函数。

**Q: 如何测试错误处理?**
A: 使用toThrow和expect.assertions验证错误路径。

Step 2: 提交文档

git add docs/testing-guide.md
git commit -m "docs: add testing guide"

Task 9: 建立覆盖率趋势监控

Files:

  • Create: scripts/coverage-trend.js
  • Create: .github/workflows/coverage-report.yml

Step 1: 创建覆盖率趋势脚本

// scripts/coverage-trend.js
const fs = require('fs');
const coverage = JSON.parse(fs.readFileSync('coverage/coverage-final.json', 'utf8'));

const metrics = {
  statements: coverage.total.statements.pct,
  branches: coverage.total.branches.pct,
  functions: coverage.total.functions.pct,
  lines: coverage.total.lines.pct,
};

console.log(JSON.stringify(metrics, null, 2));

Step 2: 创建覆盖率报告工作流

# .github/workflows/coverage-report.yml
name: Coverage Report

on:
  push:
    branches: [main]

jobs:
  report:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Generate coverage
        run: |
          npm run test:unit -- --coverage
          node scripts/coverage-trend.js > coverage-metrics.json

      - name: Upload metrics
        uses: actions/upload-artifact@v4
        with:
          name: coverage-metrics
          path: coverage-metrics.json

Step 3: 提交

git add scripts/coverage-trend.js .github/workflows/coverage-report.yml
git commit -m "ci: add coverage trend monitoring"

Task 10: 更新覆盖率目标

Files:

  • Modify: jest.config.js

Step 1: 提升覆盖率目标到35%

coverageThreshold: {
  global: {
    branches: 25,
    functions: 35,
    lines: 35,
    statements: 35,
  },
},

Step 2: 运行测试验证

Run: npm run test:unit -- --coverage --coverageReporters=text-summary

Expected: PASS with coverage above 35%

Step 3: 提交

git add jest.config.js
git commit -m "test: increase coverage threshold to 35%"

验证步骤

验证1: 确认所有测试通过

Run: npm run test:unit

Expected: All tests pass

验证2: 确认覆盖率达标

Run: npm run test:unit -- --coverage --coverageReporters=text-summary

Expected: Coverage above 35%

验证3: 确认CI构建通过

Check: GitHub Actions workflow status

Expected: All workflows pass


回滚计划

如果出现问题,可以回滚到之前的配置:

git log --oneline --all
git checkout <commit-hash>

相关资源