AIOps 智能运维平台 — TDD 开发计划
版本: v1.0
创建日期: 2026-06-21
当前覆盖率: 0% → 目标覆盖率: ≥ 50% (v0.3.0)
关联文档: PROJECT_EVALUATION.md | ROADMAP.md
一、TDD 原则
Red-Green-Refactor 循环
三条核心规则:
- 没有测试就不写产品代码 — 先写一个失败的测试,再写实现
- 每次只写刚好能通过的最少代码 — 不过度设计
- 测试通过后立即重构 — 消除重复,提升可读性
测试金字塔
二、测试框架选型
后端 (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 集成
CI 流水线 (.gitea/workflows/ci.yml)
六、覆盖率里程碑
| 版本 |
后端覆盖率 |
前端覆盖率 |
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 层次
原则:
- 数据库层: 使用 SQLite
:memory: 真实测试,不用 Mock (GORM 兼容)
- 外部服务 (K8s/Prometheus/Zabbix): 抽象为 interface,用
testify/mock 替换
- HTTP handler: 使用
httptest 发起真实 HTTP 请求测试
K8s Client Mock 示例
八、常见陷阱
- 不要 Mock 数据库 — 用 SQLite
:memory: 真实测试 GORM 逻辑,Mock DB 会漏掉 SQL 错误
- 测试必须独立 — 每个测试用例使用独立 DB 实例或事务回滚,避免数据污染
- K8s 测试不连真实集群 — 通过 interface Mock,CI 环境没有 K8s
- WebSocket 测试用 dialer — 不依赖浏览器,用
gorilla/websocket dialer 模拟
- 前端测试不依赖网络 — 用 MSW 拦截所有 API 请求
- 测试命名清晰 —
Test<函数>_<场景> 格式,如 TestLogin_WrongPassword
- 覆盖率不是目的 — 50% 覆盖核心逻辑 > 90% 覆盖 getter/setter
- 先写最难的测试 — K8s handler 99 个函数,从 cluster CRUD 开始(逻辑最核心)