graph TD
A["端到端测试 (E2E)<br/>• 用户界面测试<br/>• 完整业务流程<br/>• 执行缓慢,成本高<br/>• 数量: 5-10%"] --> B["集成测试 (Integration)<br/>• 模块间交互<br/>• 数据库/API集成<br/>• 中等执行速度<br/>• 数量: 20-30%"]
B --> C["单元测试 (Unit)<br/>• 函数/方法级别<br/>• 快速反馈<br/>• 执行速度快<br/>• 数量: 60-70%"]
style A fill:#ff9999
style B fill:#ffcc99
style C fill:#99ff99
pie title 测试类型分布
"单元测试" : 65
"集成测试" : 25
"端到端测试" : 10
flowchart TD
A["开始测试规划"] --> B{"确定测试范围"}
B --> C["单个函数/方法"]
B --> D["模块间交互"]
B --> E["完整业务流程"]
C --> F["单元测试"]
D --> G["集成测试"]
E --> H["端到端测试"]
F --> I{"是否需要性能验证?"}
G --> I
H --> I
I -->|是| J["添加性能测试"]
I -->|否| K["执行测试"]
J --> K
K --> L["分析测试结果"]
L --> M{"测试通过?"}
M -->|是| N["测试完成"]
M -->|否| O["修复问题"]
O --> K
flowchart TD
A["开始选择测试工具"] --> B{"测试类型?"}
B -->|单元测试| C{"是否需要复杂断言?"}
B -->|集成测试| D{"是否涉及数据库?"}
B -->|HTTP API测试| E["httpexpect"]
C -->|是| F["testify + assert"]
C -->|否| G["标准testing包"]
D -->|是| H["sqlmock"]
D -->|否| I{"是否涉及Redis?"}
I -->|是| J["redismock"]
I -->|否| K["testify suite"]
F --> L{"是否需要Mock?"}
G --> L
H --> L
J --> L
K --> L
E --> L
L -->|是| M["gomock"]
L -->|否| N["开始编写测试"]
M --> N
sequenceDiagram
participant T as 测试框架
participant TS as 测试套件
participant S as 用户服务
participant MD as Mock数据库
participant MC as Mock缓存
participant ML as Mock日志
T->>TS: 1. SetupTest()
TS->>MD: 创建Mock数据库
TS->>MC: 创建Mock缓存
TS->>ML: 创建Mock日志
TS->>S: 注入Mock依赖
T->>TS: 2. TestCreateUser_Success()
Note over TS: Arrange阶段
TS->>MD: 设置期望调用
TS->>MC: 设置期望调用
TS->>ML: 设置期望调用
Note over TS: Act阶段
TS->>S: CreateUser(ctx, user)
S->>MD: Create(user)
MD-->>S: 返回成功
S->>MC: Delete("users:*")
MC-->>S: 返回成功
S->>ML: Info("用户创建成功")
S-->>TS: 返回用户对象
Note over TS: Assert阶段
TS->>TS: 验证返回结果
TS->>MD: AssertExpectations()
TS->>MC: AssertExpectations()
TS->>ML: AssertExpectations()
T->>TS: 3. TearDownTest()
TS->>TS: 清理测试环境
graph TB
subgraph "测试环境"
TC["测试用例"]
TS["测试套件"]
end
subgraph "应用层"
API["HTTP API"]
SVC["业务服务"]
REPO["数据仓库"]
end
subgraph "基础设施层"
DB[("测试数据库<br/>SQLite/PostgreSQL")]
CACHE[("测试缓存<br/>Redis")]
MQ[("消息队列<br/>RabbitMQ")]
end
TC --> TS
TS --> API
API --> SVC
SVC --> REPO
REPO --> DB
SVC --> CACHE
SVC --> MQ
style TC fill:#e1f5fe
style API fill:#f3e5f5
style SVC fill:#e8f5e8
style DB fill:#fff3e0
style CACHE fill:#fce4ec
style MQ fill:#f1f8e9
flowchart TD
A["开始测试"] --> B["创建测试数据库"]
B --> C["执行数据库迁移"]
C --> D["准备测试数据"]
D --> E["执行测试用例"]
E --> F{"测试通过?"}
F -->|是| G["清理测试数据"]
F -->|否| H["记录失败信息"]
H --> G
G --> I["销毁测试数据库"]
I --> J["测试结束"]
graph TD
A["性能测试"] --> B["基准测试<br/>Benchmark"]
A --> C["负载测试<br/>Load Testing"]
A --> D["压力测试<br/>Stress Testing"]
A --> E["容量测试<br/>Volume Testing"]
A --> F["稳定性测试<br/>Endurance Testing"]
B --> B1["单个函数性能"]
B --> B2["算法效率对比"]
B --> B3["内存分配分析"]
C --> C1["预期负载下性能"]
C --> C2["响应时间验证"]
C --> C3["吞吐量测试"]
D --> D1["极限负载测试"]
D --> D2["故障恢复能力"]
D --> D3["资源耗尽场景"]
E --> E1["大数据量处理"]
E --> E2["存储容量测试"]
F --> F1["长时间运行"]
F --> F2["内存泄漏检测"]
style A fill:#e3f2fd
style B fill:#f3e5f5
style C fill:#e8f5e8
style D fill:#fff3e0
style E fill:#fce4ec
style F fill:#f1f8e9
graph TB
subgraph "测试工具层"
BT["基准测试<br/>go test -bench"]
LT["负载测试<br/>Artillery/K6"]
PT["性能分析<br/>pprof"]
end
subgraph "应用层"
API["HTTP API"]
SVC["业务服务"]
CACHE["缓存层"]
end
subgraph "数据层"
DB[("数据库")]
REDIS[("Redis")]
end
subgraph "监控层"
METRICS["指标收集"]
GRAFANA["可视化"]
ALERT["告警"]
end
BT --> API
LT --> API
PT --> SVC
API --> SVC
SVC --> CACHE
SVC --> DB
CACHE --> REDIS
API --> METRICS
SVC --> METRICS
DB --> METRICS
REDIS --> METRICS
METRICS --> GRAFANA
METRICS --> ALERT
style BT fill:#e3f2fd
style API fill:#f3e5f5
style SVC fill:#e8f5e8
style DB fill:#fff3e0
style METRICS fill:#fce4ec
flowchart TD
A["开始基准测试"] --> B["初始化测试环境"]
B --> C["预热阶段"]
C --> D["重置计时器"]
D --> E["执行测试循环"]
E --> F{"达到稳定状态?"}
F -->|否| G["调整迭代次数"]
G --> E
F -->|是| H["收集性能指标"]
H --> I["生成测试报告"]
I --> J["性能分析"]
J --> K["结束测试"]
package benchmark
import (
"context"
"testing"
"time"
"your-project/service"
"your-project/model"
)
// 用户服务基准测试
func BenchmarkUserService_CreateUser(b *testing.B) {
// 设置测试环境
db := setupTestDB()
userService := service.NewUserService(db, nil, nil)
b.ResetTimer()
for i := 0; i < b.N; i++ {
user := &model.User{
Username: fmt.Sprintf("user%d", i),
Email: fmt.Sprintf("user%[email protected]", i),
Password: "hashedpassword",
}
_, err := userService.CreateUser(context.Background(), user)
if err != nil {
b.Fatal(err)
}
}
}
// 令牌验证基准测试
func BenchmarkTokenService_ValidateToken(b *testing.B) {
db := setupTestDB()
tokenService := service.NewTokenService(db, nil)
// 预创建令牌
token, _ := tokenService.GenerateToken(context.Background(), 1, model.TokenTypeAccess, 1000000)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := tokenService.ValidateToken(context.Background(), token.Key)
if err != nil {
b.Fatal(err)
}
}
}
// 缓存性能基准测试
func BenchmarkCacheService_SetGet(b *testing.B) {
cacheService := setupTestCache()
ctx := context.Background()
b.Run("Set", func(b *testing.B) {
for i := 0; i < b.N; i++ {
key := fmt.Sprintf("key%d", i)
value := fmt.Sprintf("value%d", i)
err := cacheService.Set(ctx, key, value, time.Hour)
if err != nil {
b.Fatal(err)
}
}
})
// 预设置一些键值对
for i := 0; i < 1000; i++ {
key := fmt.Sprintf("key%d", i)
value := fmt.Sprintf("value%d", i)
cacheService.Set(ctx, key, value, time.Hour)
}
b.Run("Get", func(b *testing.B) {
for i := 0; i < b.N; i++ {
key := fmt.Sprintf("key%d", i%1000)
_, err := cacheService.Get(ctx, key)
if err != nil {
b.Fatal(err)
}
}
})
}
// 并发性能测试
func BenchmarkConcurrentTokenValidation(b *testing.B) {
db := setupTestDB()
tokenService := service.NewTokenService(db, nil)
// 预创建令牌
tokens := make([]*model.Token, 100)
for i := 0; i < 100; i++ {
token, _ := tokenService.GenerateToken(context.Background(), uint(i+1), model.TokenTypeAccess, 1000000)
tokens[i] = token
}
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
i := 0
for pb.Next() {
token := tokens[i%len(tokens)]
_, err := tokenService.ValidateToken(context.Background(), token.Key)
if err != nil {
b.Fatal(err)
}
i++
}
})
}