Files
lijiaoqiao/gateway/internal/router/strategy/ab_strategy_test.go
Your Name 89104bd0db feat(P1/P2): 完成TDD开发及P1/P2设计文档
## 设计文档
- multi_role_permission_design: 多角色权限设计 (CONDITIONAL GO)
- audit_log_enhancement_design: 审计日志增强 (CONDITIONAL GO)
- routing_strategy_template_design: 路由策略模板 (CONDITIONAL GO)
- sso_saml_technical_research: SSO/SAML调研 (CONDITIONAL GO)
- compliance_capability_package_design: 合规能力包设计 (CONDITIONAL GO)

## TDD开发成果
- IAM模块: supply-api/internal/iam/ (111个测试)
- 审计日志模块: supply-api/internal/audit/ (40+测试)
- 路由策略模块: gateway/internal/router/ (33+测试)
- 合规能力包: gateway/internal/compliance/ + scripts/ci/compliance/

## 规范文档
- parallel_agent_output_quality_standards: 并行Agent产出质量规范
- project_experience_summary: 项目经验总结 (v2)
- 2026-04-02-p1-p2-tdd-execution-plan: TDD执行计划

## 评审报告
- 5个CONDITIONAL GO设计文档评审报告
- fix_verification_report: 修复验证报告
- full_verification_report: 全面质量验证报告
- tdd_module_quality_verification: TDD模块质量验证
- tdd_execution_summary: TDD执行总结

依据: Superpowers执行框架 + TDD规范
2026-04-02 23:35:53 +08:00

162 lines
4.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package strategy
import (
"testing"
"github.com/stretchr/testify/assert"
)
// TestABStrategy_TrafficSplit 测试A/B测试流量分配
func TestABStrategy_TrafficSplit(t *testing.T) {
ab := &ABStrategy{
controlStrategy: &RoutingStrategyTemplate{ID: "control"},
experimentStrategy: &RoutingStrategyTemplate{ID: "experiment"},
trafficSplit: 20, // 20%实验组
bucketKey: "user_id",
}
// 验证流量分配
// 一致性哈希同一user_id始终分配到同一组
controlCount := 0
experimentCount := 0
for i := 0; i < 100; i++ {
userID := string(rune('0' + i))
isExperiment := ab.ShouldApplyToRequest(&RoutingRequest{UserID: userID})
if isExperiment {
experimentCount++
} else {
controlCount++
}
}
// 验证一致性同一user_id应该始终在同一组
for i := 0; i < 10; i++ {
userID := "test_user_123"
first := ab.ShouldApplyToRequest(&RoutingRequest{UserID: userID})
for j := 0; j < 10; j++ {
second := ab.ShouldApplyToRequest(&RoutingRequest{UserID: userID})
assert.Equal(t, first, second, "Same user_id should always be in same group")
}
}
// 验证分配比例大约是80:20
assert.InDelta(t, 80, controlCount, 15, "Control should be around 80%%")
assert.InDelta(t, 20, experimentCount, 15, "Experiment should be around 20%%")
}
// TestRollout_Percentage 测试灰度发布百分比递增
func TestRollout_Percentage(t *testing.T) {
rollout := &RolloutStrategy{
percentage: 10,
bucketKey: "user_id",
}
// 统计10%时的用户数
count10 := 0
for i := 0; i < 100; i++ {
userID := string(rune('0' + i))
if rollout.ShouldApply(&RoutingRequest{UserID: userID}) {
count10++
}
}
assert.InDelta(t, 10, count10, 5, "10%% rollout should have around 10 users")
// 增加百分比到20%
rollout.SetPercentage(20)
// 统计20%时的用户数
count20 := 0
for i := 0; i < 100; i++ {
userID := string(rune('0' + i))
if rollout.ShouldApply(&RoutingRequest{UserID: userID}) {
count20++
}
}
assert.InDelta(t, 20, count20, 5, "20%% rollout should have around 20 users")
// 增加百分比到50%
rollout.SetPercentage(50)
// 统计50%时的用户数
count50 := 0
for i := 0; i < 100; i++ {
userID := string(rune('0' + i))
if rollout.ShouldApply(&RoutingRequest{UserID: userID}) {
count50++
}
}
assert.InDelta(t, 50, count50, 10, "50%% rollout should have around 50 users")
// 增加百分比到100%
rollout.SetPercentage(100)
// 验证100%时所有用户都在
for i := 0; i < 100; i++ {
userID := string(rune('0' + i))
assert.True(t, rollout.ShouldApply(&RoutingRequest{UserID: userID}), "All users should be in 100% rollout")
}
}
// TestRollout_Consistency 测试灰度发布一致性
func TestRollout_Consistency(t *testing.T) {
rollout := &RolloutStrategy{
percentage: 30,
bucketKey: "user_id",
}
// 同一用户应该始终被同样对待
userID := "consistent_user"
firstResult := rollout.ShouldApply(&RoutingRequest{UserID: userID})
for i := 0; i < 100; i++ {
result := rollout.ShouldApply(&RoutingRequest{UserID: userID})
assert.Equal(t, firstResult, result, "Same user should always have same result")
}
}
// TestRollout_PercentageIncrease 测试百分比递增
func TestRollout_PercentageIncrease(t *testing.T) {
rollout := &RolloutStrategy{
percentage: 10,
bucketKey: "user_id",
}
// 收集10%时的用户
var in10Percent []string
for i := 0; i < 100; i++ {
userID := string(rune('a' + i))
if rollout.ShouldApply(&RoutingRequest{UserID: userID}) {
in10Percent = append(in10Percent, userID)
}
}
// 增加百分比到50%
rollout.SetPercentage(50)
// 收集50%时的用户
var in50Percent []string
for i := 0; i < 100; i++ {
userID := string(rune('a' + i))
if rollout.ShouldApply(&RoutingRequest{UserID: userID}) {
in50Percent = append(in50Percent, userID)
}
}
// 50%的用户应该包含10%的用户(一致性)
for _, userID := range in10Percent {
found := false
for _, id := range in50Percent {
if userID == id {
found = true
break
}
}
assert.True(t, found, "10%% users should be included in 50%% rollout")
}
// 50%应该包含更多用户
assert.Greater(t, len(in50Percent), len(in10Percent), "50%% should have more users than 10%%")
}