chore: remove GitHub Actions workflows, use Woodpecker CI exclusively

This commit is contained in:
张翔
2026-03-10 13:10:11 +08:00
parent 0a1adfc2a2
commit e8dffa4f05
82 changed files with 19565 additions and 101 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,579 @@
# 渐进式测试覆盖率提升计划
> **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: 修改覆盖率阈值为合理水平**
```javascript
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: 提交配置修改**
```bash
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管理编写测试**
```typescript
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管理功能**
```typescript
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: 提交**
```bash
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: 编写数据验证测试**
```typescript
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: 实现验证函数**
```typescript
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: 提交**
```bash
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: 配置并行测试执行**
```javascript
// jest.config.js
module.exports = {
// ... existing config
maxWorkers: '50%',
};
```
**Step 2: 创建优化后的CI工作流**
```yaml
# .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: 提交配置**
```bash
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路由测试**
```typescript
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路由验证逻辑**
```typescript
// 确保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: 提交**
```bash
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: 编写数据库查询测试**
```typescript
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: 实现数据库查询函数**
```typescript
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: 提交**
```bash
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: 添加边界条件测试**
```typescript
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: 提交**
```bash
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: 编写测试指南**
```markdown
# 测试指南
## 测试策略
本项目采用分层覆盖率策略:
- 核心业务逻辑层: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: 提交文档**
```bash
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: 创建覆盖率趋势脚本**
```javascript
// 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: 创建覆盖率报告工作流**
```yaml
# .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: 提交**
```bash
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%**
```javascript
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: 提交**
```bash
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
---
## 回滚计划
如果出现问题,可以回滚到之前的配置:
```bash
git log --oneline --all
git checkout <commit-hash>
```
---
## 相关资源
- [Jest文档](https://jestjs.io/docs/getting-started)
- [React Testing Library](https://testing-library.com/docs/react-testing-library/intro)
- [测试最佳实践](https://github.com/goldbergyoni/javascript-testing-best-practices)
File diff suppressed because it is too large Load Diff