Files
aiops/TDD_PLAN.md
T
attacker 3b112ee813 docs: 添加项目评估、开发路线图、TDD开发计划三份核心文档
- PROJECT_EVALUATION.md: 综合评分72/100,15模块全量审计,工程质量(零测试)为最大风险
- ROADMAP.md: v0.3.0质量加固(当前)→v0.4.0企业级→v1.0.0智能化,含技术债务清单
- TDD_PLAN.md: 后端3阶段测试计划(覆盖率0%→50%),含K8s/Auth/Pipeline具体测试函数
2026-06-21 21:20:04 +08:00

16 KiB

AIOps 智能运维平台 — TDD 开发计划

版本: v1.0 创建日期: 2026-06-21 当前覆盖率: 0% → 目标覆盖率: ≥ 50% (v0.3.0) 关联文档: PROJECT_EVALUATION.md | ROADMAP.md


一、TDD 原则

Red-Green-Refactor 循环

    ┌──────────┐     ┌──────────┐     ┌──────────┐
    │  🔴 RED  │ ──► │ 🟢 GREEN │ ──► │ 🔵 REFACT│
    │ 写失败测试 │     │ 最快实现  │     │ 消除重复  │
    └──────────┘     └──────────┘     └──────────┘
         ▲                                    │
         └────────────────────────────────────┘
                       循环

三条核心规则:

  1. 没有测试就不写产品代码 — 先写一个失败的测试,再写实现
  2. 每次只写刚好能通过的最少代码 — 不过度设计
  3. 测试通过后立即重构 — 消除重复,提升可读性

测试金字塔

                    ╱╲
                   ╱E2E╲           ← 少量 (Playwright, ~5%)
                  ╱──────╲
                 ╱ 集成测试 ╲       ← 适量 (httptest + DB, ~25%)
                ╱────────────╲
               ╱   单元测试    ╲    ← 大量 (纯函数/逻辑, ~70%)
              ╱──────────────────╲

二、测试框架选型

后端 (Go)

工具 用途 引入方式
testing (标准库) 测试运行器 内置
testify/assert 断言库 go get github.com/stretchr/testify/assert
testify/require 致命断言 同上
testify/mock Mock 框架 同上
net/http/httptest HTTP handler 测试 内置
gorm.io/driver/sqlite :memory: 内存数据库测试 已有依赖
swaggo/swag (可选) API 文档 go get github.com/swaggo/swag/cmd/swag

前端 (React)

工具 用途 引入方式
vitest 测试运行器 npm i -D vitest
@testing-library/react 组件测试 npm i -D @testing-library/react
@testing-library/jest-dom DOM 断言 npm i -D @testing-library/jest-dom
@testing-library/user-event 用户交互模拟 npm i -D @testing-library/user-event
msw API Mock npm i -D msw
@playwright/test E2E 测试 npm i -D @playwright/test

三、后端逐模块测试计划

阶段 1: 核心模块 (第 1-2 周) — 目标覆盖率 40%

1.1 认证模块 (user.go, user_admin.go)

测试文件 测试函数 覆盖场景 优先级
user_test.go TestLogin_Success 正确用户名密码 → 200 + JWT P0
TestLogin_WrongPassword 错误密码 → 401 P0
TestLogin_UserNotFound 不存在用户 → 401 P0
TestRegister_Success 正常注册 → 201 P0
TestRegister_DuplicateUsername 重复用户名 → 409 P0
TestGetProfile_Authenticated 带 JWT → 200 + 用户信息 P0
TestGetProfile_NoAuth 无 JWT → 401 P0
TestChangePassword_Success 正确旧密码 → 200 P1
TestChangePassword_WrongOld 错误旧密码 → 400 P1
TestJWTAuth_ValidToken 有效 JWT → 放行 P0
TestJWTAuth_ExpiredToken 过期 JWT → 401 P0
TestJWTAuth_MalformedToken 畸形 JWT → 401 P1

1.2 Kubernetes 模块 (kubernetes.go) — 最高优先级

测试文件 测试函数 覆盖场景 优先级
kubernetes_cluster_test.go TestListClusters_Empty 空列表 → 200 + [] P0
TestListClusters_With3Records 3 条记录 → 200 + 3 items P0
TestCreateCluster_ValidInput 合法 Name/Code → 201 P0
TestCreateCluster_InvalidName Name 含中文/空格 → 400 P0
TestCreateCluster_DuplicateCode 重复 Code → 409 P0
TestGetCluster_Found 存在的 ID → 200 P0
TestGetCluster_NotFound 不存在的 ID → 404 P0
TestUpdateCluster_Success 更新名称 → 200 P1
TestDeleteCluster_Success 删除 → 200 P1
TestDeleteCluster_NotFound 删除不存在 → 404 P1
TestSyncCluster_Success 同步集群资源 → 200 + 统计 P0
TestResolveClusterCode_Valid code 解析 → cluster ID P0
TestResolveClusterCode_NotFound 无效 code → 错误 P0
kubernetes_workload_test.go TestListDeployments_NS 按命名空间过滤 → 200 P0
TestScaleDeployment_Up 扩容 1→3 → 200 + replicas=3 P0
TestScaleDeployment_Down 缩容 3→1 → 200 P1
TestRestartDeployment_Success 滚动重启 → 200 P0
TestUpdateDeploymentImage_Success 更新镜像 → 200 P1
TestListHPAs_NS HPA 列表 → 200 P1
TestCreateHPA_Valid 创建 HPA → 201 P1
TestDeleteHPA_Success 删除 HPA → 200 P2
TestListCronJobs_NS CronJob 列表 → 200 P1
TestCreateCronJob_Valid 创建 CronJob → 201 P1
TestSuspendCronJob_Success 挂起 → 200 P2
TestTriggerCronJob_Success 手动触发 → 200 P2

注意: K8s 测试需要 Mock kubernetesclient.Client 接口,不依赖真实集群。使用 testify/mock 或接口抽象。

1.3 CI/CD Pipeline 模块 (pipeline.go, pipeline_executor.go)

测试文件 测试函数 覆盖场景 优先级
pipeline_test.go TestCreatePipeline_Valid 合法配置 → 201 P0
TestCreatePipeline_DuplicateCode 重复 code → 409 P0
TestListPipelines_Pagination 分页 → 正确总数+页 P1
TestGetPipeline_Found 查询 → 200 P0
TestUpdatePipeline_Success 更新 → 200 P1
TestDeletePipeline_Success 删除 → 200 P1
TestWebhookTrigger_Valid Webhook 触发 → 200 + run P0
pipeline_executor_test.go TestExecutePipeline_AllStepsPass 全步骤通过 → success P0
TestExecutePipeline_StepFail 步骤失败 → failed P0
TestExecutePipeline_Conditional 条件步骤 → skip/execute P1

阶段 2: 监控/告警模块 (第 3 周) — 目标覆盖率 50%

2.1 告警引擎 (alert_engine.go, alert_rules.go)

测试文件 测试函数 覆盖场景 优先级
alert_engine_test.go TestEvaluateRule_ThresholdExceeded CPU > 90% → 触发 P0
TestEvaluateRule_ThresholdNormal CPU < 90% → 不触发 P0
TestEvaluateRule_OfflineDetection Agent 离线 → 触发 P0
TestEvaluateRule_SilencedPeriod 静默期内 → 不触发 P1
TestSendAlert_AllChannels 通知全渠道 → 计数正确 P1
alert_rules_test.go TestCreateAlertRule_Valid 创建规则 → 201 P1
TestListAlertRules_BySeverity 按级别过滤 → 200 P1
TestUpdateAlertRule_Toggle 启用/禁用 → 200 P2

2.2 服务器管理 (server.go)

测试文件 测试函数 覆盖场景 优先级
server_test.go TestListServers_Pagination 分页 → 正确 P1
TestCreateServer_Valid 合法 → 201 P1
TestBatchCreateServers_3Items 批量创建 3 条 → 201 P1
TestBatchDeleteServers_3IDs 批量删除 → 200 P2
TestGetServerStats_Aggregation 统计聚合 → 正确数字 P2

2.3 云资源 (cloud_accounts.go, cloud_sync.go)

测试文件 测试函数 覆盖场景 优先级
cloud_accounts_test.go TestCreateCloudAccount_Valid 合法 → 201 P1
TestCreateCloudAccount_InvalidAK 空 AK → 400 P2
TestListCloudAccounts_ByPlatform 按平台过滤 → 200 P2
cloud_sync_test.go TestDiscoverInstances_MockProvider Mock 云 API → 正确实例 P2

阶段 3: 补全覆盖 (第 4 周) — 目标覆盖率 50%+

3.1 Agent / 自动化 / 审批

测试文件 测试函数 覆盖场景 优先级
agent_test.go TestRegisterAgent_New 新注册 → 201 P1
TestAgentHeartbeat_Update 心跳 → 更新时间 P1
TestAssignTask_AvailableAgent 分配任务 → 200 P2
automation_cron_test.go TestCreateCronJob_Valid 创建定时任务 → 201 P1
TestListCronJobs_FilterByStatus 按状态过滤 → 200 P2
approval_test.go TestCreateApprovalRequest_Valid 创建审批 → 201 P1
TestApproveRequest_Success 审批通过 → 200 P1
TestRejectRequest_WithReason 审批拒绝 → 200 P2
audit_test.go TestListAuditLogs_Pagination 审计日志分页 → 200 P2
TestExportAuditLogs_CSV CSV 导出 → 200 + text/csv P2

四、前端测试计划

阶段 1: 基建 + 核心组件 (第 2-3 周)

4.1 单元测试 (Vitest)

测试文件 覆盖场景 优先级
api.test.ts API 函数参数构造/响应解析 Mock P1
auth/LoginForm.test.tsx 表单验证/提交/错误展示 P0
kubernetes/KubernetesClusters.test.tsx 集群列表渲染/创建对话框 P0
kubernetes/DeploymentDetail.test.tsx Deployment 详情渲染/操作按钮 P1
server/ServerManager.test.tsx 服务器列表/搜索/分页 P1
dashboard/StatsCard.test.tsx 统计卡片数据渲染 P2

4.2 E2E 测试 (Playwright) — 冒烟流程

测试文件 覆盖流程 优先级
e2e/login.spec.ts 登录 → 跳转仪表盘 → 验证菜单 P0
e2e/server-list.spec.ts 服务器列表 → 搜索 → 查看详情 → WebShell P1
e2e/k8s-cluster.spec.ts K8s 集群 → 工作负载 → Deployment 详情 → 日志 P1

五、测试执行策略

三级执行体系

级别 触发时机 执行内容 耗时目标
日常开发 git commit (pre-push hook) 后端单元测试 + lint < 30s
PR 检查 PR 创建/更新 (CI) 全量测试 + lint + build + 覆盖率 < 5min
发布门禁 tag/release (CI) 全量 + E2E + 安全扫描 + 3 种部署验证 < 15min

Makefile 集成

# 后端测试
test:
	cd backend && go test ./... -v -count=1

test-cover:
	cd backend && go test ./... -coverprofile=coverage.out -covermode=atomic
	go tool cover -html=coverage.out -o coverage.html

test-short:
	cd backend && go test ./... -v -short -count=1

# 前端测试
test-fe:
	cd frontend && npx vitest run

test-fe-watch:
	cd frontend && npx vitest

test-e2e:
	cd frontend && npx playwright test

# 全量测试
test-all: test-cover test-fe test-e2e
	@echo "✅ All tests passed"

# lint
lint:
	cd backend && golangci-lint run
	cd frontend && npx eslint src --max-warnings 0

CI 流水线 (.gitea/workflows/ci.yml)

name: CI
on: [push, pull_request]

jobs:
  backend-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-go@v5
        with:
          go-version: '1.24'
      - run: cd backend && go vet ./...
      - run: cd backend && golangci-lint run
      - run: cd backend && go test ./... -coverprofile=coverage.out -race
      - run: cd backend && go tool cover -func=coverage.out

  frontend-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: cd frontend && npm ci
      - run: cd frontend && npx vitest run --coverage
      - run: cd frontend && npx tsc --noEmit

  build:
    needs: [backend-test, frontend-test]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: make build

六、覆盖率里程碑

版本 后端覆盖率 前端覆盖率 E2E 覆盖 说明
当前 0% 0% 0% 零起点
v0.3.0 Sprint 1 15% 5% 0% 核心模块首批测试
v0.3.0 Sprint 2 30% 10% 0% K8s 全覆盖 + 重构
v0.3.0 Sprint 3 45% 15% 3 条 监控/告警 + E2E 冒烟
v0.3.0 发布 ≥ 50% ≥ 15% 3 条 质量加固验收
v0.4.0 ≥ 65% ≥ 30% 8 条 企业级特性 + 测试增强
v1.0.0 ≥ 75% ≥ 50% 20 条 智能化 + 全量覆盖

覆盖率豁免规则

以下代码允许低覆盖率:

  • main.go / cmd/ — 入口文件,由 E2E 覆盖
  • scripts/ — 种子数据/Mock 脚本
  • WebSocket handler — 由集成测试覆盖
  • pkg/crypto — 安全敏感,由专项安全测试覆盖

七、Mock 策略

后端 Mock 层次

┌─────────────────────────────────────┐
│         HTTP Handler Test           │  ← httptest.NewServer
├─────────────────────────────────────┤
│         Service / Business          │  ← 接口注入 Mock
├─────────────────────────────────────┤
│         Data Access (GORM)          │  ← SQLite :memory: 真实 DB
├─────────────────────────────────────┤
│    External (K8s/Prometheus/SSH)    │  ← Interface Mock
└─────────────────────────────────────┘

原则:

  • 数据库层: 使用 SQLite :memory: 真实测试,不用 Mock (GORM 兼容)
  • 外部服务 (K8s/Prometheus/Zabbix): 抽象为 interface,用 testify/mock 替换
  • HTTP handler: 使用 httptest 发起真实 HTTP 请求测试

K8s Client Mock 示例

// 定义 interface (如果没有的话)
type K8sClientInterface interface {
    ListDeployments(namespace string) ([]appsv1.Deployment, error)
    ScaleDeployment(name, namespace string, replicas int32) error
    // ...
}

// Mock 实现
type MockK8sClient struct {
    mock.Mock
}

func (m *MockK8sClient) ListDeployments(ns string) ([]appsv1.Deployment, error) {
    args := m.Called(ns)
    return args.Get(0).([]appsv1.Deployment), args.Error(1)
}

// 测试中使用
func TestListDeployments_NS(t *testing.T) {
    mockClient := new(MockK8sClient)
    mockClient.On("ListDeployments", "default").Return([]appsv1.Deployment{...}, nil)
    
    handler := &KubernetesHandler{k8sClient: mockClient, db: testDB}
    // ... HTTP 测试
}

八、常见陷阱

  1. 不要 Mock 数据库 — 用 SQLite :memory: 真实测试 GORM 逻辑,Mock DB 会漏掉 SQL 错误
  2. 测试必须独立 — 每个测试用例使用独立 DB 实例或事务回滚,避免数据污染
  3. K8s 测试不连真实集群 — 通过 interface Mock,CI 环境没有 K8s
  4. WebSocket 测试用 dialer — 不依赖浏览器,用 gorilla/websocket dialer 模拟
  5. 前端测试不依赖网络 — 用 MSW 拦截所有 API 请求
  6. 测试命名清晰 — Test<函数>_<场景> 格式,如 TestLogin_WrongPassword
  7. 覆盖率不是目的 — 50% 覆盖核心逻辑 > 90% 覆盖 getter/setter
  8. 先写最难的测试 — K8s handler 99 个函数,从 cluster CRUD 开始(逻辑最核心)