test: 完善自动化测试体系(7个模块,73个任务)
系统性地修复、补充和强化项目的自动化测试能力: 1. 测试基础设施修复 - 修复 stubConcurrencyCache 缺失方法和构造函数参数不匹配 - 创建 testutil 共享包(stubs.go, fixtures.go, httptest.go) - 为所有 Stub 添加编译期接口断言 2. 中间件测试补充 - 新增 JWT 认证中间件测试(有效/过期/篡改/缺失 Token) - 补充 rate_limiter 和 recovery 中间件测试场景 3. 网关核心路径测试 - 新增账户选择、等待队列、流式响应、并发控制、计费、Claude Code 检测测试 - 覆盖负载均衡、粘性会话、SSE 转发、槽位管理等关键逻辑 4. 前端测试体系(11个新测试文件,163个测试用例) - Pinia stores: auth, app, subscriptions - API client: 请求拦截器、响应拦截器、401 刷新 - Router guards: 认证重定向、管理员权限、简易模式限制 - Composables: useForm, useTableLoader, useClipboard - Components: LoginForm, ApiKeyCreate, Dashboard 5. CI/CD 流水线重构 - 重构 backend-ci.yml 为统一的 ci.yml - 前后端 4 个并行 Job + Postgres/Redis services - Race 检测、覆盖率收集与门禁、Docker 构建验证 6. E2E 自动化测试 - e2e-test.sh 自动化脚本(Docker 启动→健康检查→测试→清理) - 用户注册→登录→API Key→网关调用完整链路测试 - Mock 模式和 API Key 脱敏支持 7. 修复预存问题 - tlsfingerprint dialer_test.go 缺失 build tag 导致集成测试编译冲突 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
179
.github/workflows/ci.yml
vendored
Normal file
179
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
# ==========================================================================
|
||||
# 后端测试(与前端并行运行)
|
||||
# ==========================================================================
|
||||
backend-test:
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
env:
|
||||
POSTGRES_USER: test
|
||||
POSTGRES_PASSWORD: test
|
||||
POSTGRES_DB: sub2api_test
|
||||
ports:
|
||||
- 5432:5432
|
||||
options: >-
|
||||
--health-cmd "pg_isready -U test"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
ports:
|
||||
- 6379:6379
|
||||
options: >-
|
||||
--health-cmd "redis-cli ping"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: backend/go.mod
|
||||
check-latest: false
|
||||
cache: true
|
||||
|
||||
- name: 验证 Go 版本
|
||||
run: go version | grep -q 'go1.25.7'
|
||||
|
||||
- name: 单元测试
|
||||
working-directory: backend
|
||||
run: make test-unit
|
||||
|
||||
- name: 集成测试
|
||||
working-directory: backend
|
||||
env:
|
||||
DATABASE_URL: postgres://test:test@localhost:5432/sub2api_test?sslmode=disable
|
||||
REDIS_URL: redis://localhost:6379/0
|
||||
run: make test-integration
|
||||
|
||||
- name: Race 检测
|
||||
working-directory: backend
|
||||
run: go test -tags=unit -race -count=1 ./...
|
||||
|
||||
- name: 覆盖率收集
|
||||
working-directory: backend
|
||||
run: |
|
||||
go test -tags=unit -coverprofile=coverage.out -count=1 ./...
|
||||
echo "## 后端测试覆盖率" >> $GITHUB_STEP_SUMMARY
|
||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||
go tool cover -func=coverage.out | tail -1 >> $GITHUB_STEP_SUMMARY
|
||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: 覆盖率门禁(≥8%)
|
||||
working-directory: backend
|
||||
run: |
|
||||
COVERAGE=$(go tool cover -func=coverage.out | tail -1 | awk '{print $3}' | sed 's/%//')
|
||||
echo "当前覆盖率: ${COVERAGE}%"
|
||||
if [ "$(echo "$COVERAGE < 8" | bc -l)" -eq 1 ]; then
|
||||
echo "::error::后端覆盖率 ${COVERAGE}% 低于门禁值 8%"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ==========================================================================
|
||||
# 后端代码检查
|
||||
# ==========================================================================
|
||||
golangci-lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: backend/go.mod
|
||||
check-latest: false
|
||||
cache: true
|
||||
- name: 验证 Go 版本
|
||||
run: go version | grep -q 'go1.25.7'
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v9
|
||||
with:
|
||||
version: v2.7
|
||||
args: --timeout=5m
|
||||
working-directory: backend
|
||||
|
||||
# ==========================================================================
|
||||
# 前端测试(与后端并行运行)
|
||||
# ==========================================================================
|
||||
frontend-test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: 安装 pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 9
|
||||
- name: 安装 Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'pnpm'
|
||||
cache-dependency-path: frontend/pnpm-lock.yaml
|
||||
- name: 安装依赖
|
||||
working-directory: frontend
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: 类型检查
|
||||
working-directory: frontend
|
||||
run: pnpm run typecheck
|
||||
|
||||
- name: Lint 检查
|
||||
working-directory: frontend
|
||||
run: pnpm run lint:check
|
||||
|
||||
- name: 单元测试
|
||||
working-directory: frontend
|
||||
run: pnpm run test:run
|
||||
|
||||
- name: 覆盖率收集
|
||||
working-directory: frontend
|
||||
run: |
|
||||
pnpm run test:coverage -- --exclude '**/integration/**' || true
|
||||
echo "## 前端测试覆盖率" >> $GITHUB_STEP_SUMMARY
|
||||
if [ -f coverage/coverage-final.json ]; then
|
||||
echo "覆盖率报告已生成" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
- name: 覆盖率门禁(≥20%)
|
||||
working-directory: frontend
|
||||
run: |
|
||||
if [ ! -f coverage/coverage-final.json ]; then
|
||||
echo "::warning::覆盖率报告未生成,跳过门禁检查"
|
||||
exit 0
|
||||
fi
|
||||
# 使用 node 解析覆盖率 JSON
|
||||
COVERAGE=$(node -e "
|
||||
const data = require('./coverage/coverage-final.json');
|
||||
let totalStatements = 0, coveredStatements = 0;
|
||||
for (const file of Object.values(data)) {
|
||||
const stmts = file.s;
|
||||
totalStatements += Object.keys(stmts).length;
|
||||
coveredStatements += Object.values(stmts).filter(v => v > 0).length;
|
||||
}
|
||||
const pct = totalStatements > 0 ? (coveredStatements / totalStatements * 100) : 0;
|
||||
console.log(pct.toFixed(1));
|
||||
")
|
||||
echo "当前前端覆盖率: ${COVERAGE}%"
|
||||
if [ "$(echo "$COVERAGE < 20" | bc -l 2>/dev/null || node -e "console.log($COVERAGE < 20 ? 1 : 0)")" = "1" ]; then
|
||||
echo "::warning::前端覆盖率 ${COVERAGE}% 低于门禁值 20%(当前为警告,不阻塞)"
|
||||
fi
|
||||
|
||||
# ==========================================================================
|
||||
# Docker 构建验证
|
||||
# ==========================================================================
|
||||
docker-build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Docker 构建验证
|
||||
run: docker build -t aicodex2api:ci-test .
|
||||
Reference in New Issue
Block a user