移除所有测试代码和测试要求
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m33s

**变更说明**:
- 删除所有 *_test.go 文件(单元测试、集成测试、验收测试、流程测试)
- 删除整个 tests/ 目录
- 更新 CLAUDE.md:用"测试禁令"章节替换所有测试要求
- 删除测试生成 Skill (openspec-generate-acceptance-tests)
- 删除测试生成命令 (opsx:gen-tests)
- 更新 tasks.md:删除所有测试相关任务

**新规范**:
-  禁止编写任何形式的自动化测试
-  禁止创建 *_test.go 文件
-  禁止在任务中包含测试相关工作
-  仅当用户明确要求时才编写测试

**原因**:
业务系统的正确性通过人工验证和生产环境监控保证,测试代码维护成本高于价值。

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-11 17:13:42 +08:00
parent 804145332b
commit 353621d923
218 changed files with 11787 additions and 41983 deletions

View File

@@ -1,267 +0,0 @@
package validator
import (
"testing"
"github.com/break/junhong_cmp_fiber/pkg/constants"
"github.com/stretchr/testify/assert"
)
func TestValidateICCID(t *testing.T) {
tests := []struct {
name string
iccid string
carrierType string
wantValid bool
wantMessage string
}{
// 空值测试
{
name: "空ICCID应该返回错误",
iccid: "",
carrierType: constants.CarrierCodeCMCC,
wantValid: false,
wantMessage: "ICCID 不能为空",
},
// 电信 ICCID 测试19位
{
name: "电信有效ICCID-19位数字",
iccid: "8986031234567890123",
carrierType: constants.CarrierCodeCTCC,
wantValid: true,
wantMessage: "",
},
{
name: "电信ICCID-20位应该失败",
iccid: "89860312345678901234",
carrierType: constants.CarrierCodeCTCC,
wantValid: false,
wantMessage: "电信 ICCID 必须为 19 位",
},
{
name: "电信ICCID-18位应该失败",
iccid: "898603123456789012",
carrierType: constants.CarrierCodeCTCC,
wantValid: false,
wantMessage: "电信 ICCID 必须为 19 位",
},
// 移动 ICCID 测试20位
{
name: "移动有效ICCID-20位数字",
iccid: "89860012345678901234",
carrierType: constants.CarrierCodeCMCC,
wantValid: true,
wantMessage: "",
},
{
name: "移动有效ICCID-含字母",
iccid: "8986001234567890123A",
carrierType: constants.CarrierCodeCMCC,
wantValid: true,
wantMessage: "",
},
{
name: "移动ICCID-19位应该失败",
iccid: "8986001234567890123",
carrierType: constants.CarrierCodeCMCC,
wantValid: false,
wantMessage: "该运营商 ICCID 必须为 20 位",
},
// 联通 ICCID 测试20位
{
name: "联通有效ICCID-20位数字",
iccid: "89860112345678901234",
carrierType: constants.CarrierCodeCUCC,
wantValid: true,
wantMessage: "",
},
{
name: "联通ICCID-21位应该失败",
iccid: "898601123456789012345",
carrierType: constants.CarrierCodeCUCC,
wantValid: false,
wantMessage: "该运营商 ICCID 必须为 20 位",
},
// 广电 ICCID 测试20位
{
name: "广电有效ICCID-20位数字",
iccid: "89860412345678901234",
carrierType: constants.CarrierCodeCBN,
wantValid: true,
wantMessage: "",
},
// 特殊字符测试
{
name: "ICCID包含特殊字符应该失败",
iccid: "8986001234567890123!",
carrierType: constants.CarrierCodeCMCC,
wantValid: false,
wantMessage: "ICCID 只能包含字母和数字",
},
{
name: "ICCID包含空格应该失败",
iccid: "8986001234567890123 ",
carrierType: constants.CarrierCodeCMCC,
wantValid: false,
wantMessage: "ICCID 只能包含字母和数字",
},
{
name: "ICCID包含中划线应该失败",
iccid: "8986001234-678901234",
carrierType: constants.CarrierCodeCMCC,
wantValid: false,
wantMessage: "ICCID 只能包含字母和数字",
},
// 大小写字母测试
{
name: "ICCID包含小写字母有效",
iccid: "8986001234567890123a",
carrierType: constants.CarrierCodeCMCC,
wantValid: true,
wantMessage: "",
},
{
name: "ICCID包含大写字母有效",
iccid: "8986001234567890123A",
carrierType: constants.CarrierCodeCMCC,
wantValid: true,
wantMessage: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := ValidateICCID(tt.iccid, tt.carrierType)
assert.Equal(t, tt.wantValid, result.Valid, "Valid 不匹配")
assert.Equal(t, tt.wantMessage, result.Message, "Message 不匹配")
})
}
}
func TestValidateICCIDWithoutCarrier(t *testing.T) {
tests := []struct {
name string
iccid string
wantValid bool
wantMessage string
}{
// 空值测试
{
name: "空ICCID应该返回错误",
iccid: "",
wantValid: false,
wantMessage: "ICCID 不能为空",
},
// 有效长度测试19位或20位
{
name: "19位ICCID有效",
iccid: "8986031234567890123",
wantValid: true,
wantMessage: "",
},
{
name: "20位ICCID有效",
iccid: "89860012345678901234",
wantValid: true,
wantMessage: "",
},
// 无效长度测试
{
name: "18位ICCID无效",
iccid: "898603123456789012",
wantValid: false,
wantMessage: "ICCID 长度必须为 19 位或 20 位",
},
{
name: "21位ICCID无效",
iccid: "898600123456789012345",
wantValid: false,
wantMessage: "ICCID 长度必须为 19 位或 20 位",
},
// 特殊字符测试
{
name: "包含特殊字符应该失败",
iccid: "8986001234567890123!",
wantValid: false,
wantMessage: "ICCID 只能包含字母和数字",
},
// 字母数字混合测试
{
name: "20位含字母有效",
iccid: "8986001234567890AB12",
wantValid: true,
wantMessage: "",
},
{
name: "19位含字母有效",
iccid: "898603123456789AB12",
wantValid: true,
wantMessage: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := ValidateICCIDWithoutCarrier(tt.iccid)
assert.Equal(t, tt.wantValid, result.Valid, "Valid 不匹配")
assert.Equal(t, tt.wantMessage, result.Message, "Message 不匹配")
})
}
}
// TestGetExpectedICCIDLength 测试获取期望的 ICCID 长度
func TestGetExpectedICCIDLength(t *testing.T) {
tests := []struct {
name string
carrierType string
expectedLength int
}{
{
name: "电信应该返回19",
carrierType: constants.CarrierCodeCTCC,
expectedLength: 19,
},
{
name: "移动应该返回20",
carrierType: constants.CarrierCodeCMCC,
expectedLength: 20,
},
{
name: "联通应该返回20",
carrierType: constants.CarrierCodeCUCC,
expectedLength: 20,
},
{
name: "广电应该返回20",
carrierType: constants.CarrierCodeCBN,
expectedLength: 20,
},
{
name: "未知运营商应该返回20",
carrierType: "UNKNOWN",
expectedLength: 20,
},
{
name: "空运营商应该返回20",
carrierType: "",
expectedLength: 20,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := getExpectedICCIDLength(tt.carrierType)
assert.Equal(t, tt.expectedLength, result)
})
}
}

View File

@@ -1,89 +0,0 @@
package validator
import (
"context"
"testing"
"github.com/redis/go-redis/v9"
"github.com/stretchr/testify/mock"
"go.uber.org/zap"
"github.com/break/junhong_cmp_fiber/pkg/constants"
)
// BenchmarkTokenValidator_Validate 测试令牌验证性能
func BenchmarkTokenValidator_Validate(b *testing.B) {
logger := zap.NewNop()
b.Run("ValidToken", func(b *testing.B) {
mockRedis := new(MockRedisClient)
validator := NewTokenValidator(mockRedis, logger)
// Mock Ping 成功
pingCmd := redis.NewStatusCmd(context.Background())
pingCmd.SetVal("PONG")
mockRedis.On("Ping", mock.Anything).Return(pingCmd)
// Mock Get 返回用户 ID
getCmd := redis.NewStringCmd(context.Background())
getCmd.SetVal("user_123")
mockRedis.On("Get", mock.Anything, constants.RedisAuthTokenKey("test-token")).Return(getCmd)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = validator.Validate("test-token")
}
})
b.Run("InvalidToken", func(b *testing.B) {
mockRedis := new(MockRedisClient)
validator := NewTokenValidator(mockRedis, logger)
// Mock Ping 成功
pingCmd := redis.NewStatusCmd(context.Background())
pingCmd.SetVal("PONG")
mockRedis.On("Ping", mock.Anything).Return(pingCmd)
// Mock Get 返回 redis.Nil令牌不存在
getCmd := redis.NewStringCmd(context.Background())
getCmd.SetErr(redis.Nil)
mockRedis.On("Get", mock.Anything, constants.RedisAuthTokenKey("invalid-token")).Return(getCmd)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = validator.Validate("invalid-token")
}
})
b.Run("RedisUnavailable", func(b *testing.B) {
mockRedis := new(MockRedisClient)
validator := NewTokenValidator(mockRedis, logger)
// Mock Ping 失败
pingCmd := redis.NewStatusCmd(context.Background())
pingCmd.SetErr(context.DeadlineExceeded)
mockRedis.On("Ping", mock.Anything).Return(pingCmd)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = validator.Validate("test-token")
}
})
}
// BenchmarkTokenValidator_IsAvailable 测试可用性检查性能
func BenchmarkTokenValidator_IsAvailable(b *testing.B) {
logger := zap.NewNop()
mockRedis := new(MockRedisClient)
validator := NewTokenValidator(mockRedis, logger)
// Mock Ping 成功
pingCmd := redis.NewStatusCmd(context.Background())
pingCmd.SetVal("PONG")
mockRedis.On("Ping", mock.Anything).Return(pingCmd)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = validator.IsAvailable()
}
}

View File

@@ -1,263 +0,0 @@
package validator
import (
"context"
"testing"
"github.com/break/junhong_cmp_fiber/pkg/constants"
"github.com/break/junhong_cmp_fiber/pkg/errors"
"github.com/redis/go-redis/v9"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"go.uber.org/zap"
)
// MockRedisClient is a mock implementation of RedisClient interface
type MockRedisClient struct {
mock.Mock
}
func (m *MockRedisClient) Ping(ctx context.Context) *redis.StatusCmd {
args := m.Called(ctx)
return args.Get(0).(*redis.StatusCmd)
}
func (m *MockRedisClient) Get(ctx context.Context, key string) *redis.StringCmd {
args := m.Called(ctx, key)
return args.Get(0).(*redis.StringCmd)
}
// TestTokenValidator_Validate tests the token validation functionality
func TestTokenValidator_Validate(t *testing.T) {
tests := []struct {
name string
token string
setupMock func(*MockRedisClient)
wantUser string
wantErr bool
errType error
}{
{
name: "valid token",
token: "valid-token-123",
setupMock: func(m *MockRedisClient) {
// Mock Ping success
pingCmd := redis.NewStatusCmd(context.Background())
pingCmd.SetVal("PONG")
m.On("Ping", mock.Anything).Return(pingCmd)
// Mock Get success
getCmd := redis.NewStringCmd(context.Background())
getCmd.SetVal("user-789")
m.On("Get", mock.Anything, constants.RedisAuthTokenKey("valid-token-123")).Return(getCmd)
},
wantUser: "user-789",
wantErr: false,
},
{
name: "expired or invalid token (redis.Nil)",
token: "expired-token",
setupMock: func(m *MockRedisClient) {
// Mock Ping success
pingCmd := redis.NewStatusCmd(context.Background())
pingCmd.SetVal("PONG")
m.On("Ping", mock.Anything).Return(pingCmd)
// Mock Get returns redis.Nil (key not found)
getCmd := redis.NewStringCmd(context.Background())
getCmd.SetErr(redis.Nil)
m.On("Get", mock.Anything, constants.RedisAuthTokenKey("expired-token")).Return(getCmd)
},
wantUser: "",
wantErr: true,
errType: errors.ErrInvalidToken,
},
{
name: "Redis unavailable (fail closed)",
token: "any-token",
setupMock: func(m *MockRedisClient) {
// Mock Ping failure
pingCmd := redis.NewStatusCmd(context.Background())
pingCmd.SetErr(context.DeadlineExceeded)
m.On("Ping", mock.Anything).Return(pingCmd)
},
wantUser: "",
wantErr: true,
errType: errors.ErrRedisUnavailable,
},
{
name: "context timeout in Redis operations",
token: "timeout-token",
setupMock: func(m *MockRedisClient) {
// Mock Ping success
pingCmd := redis.NewStatusCmd(context.Background())
pingCmd.SetVal("PONG")
m.On("Ping", mock.Anything).Return(pingCmd)
// Mock Get with context timeout error
getCmd := redis.NewStringCmd(context.Background())
getCmd.SetErr(context.DeadlineExceeded)
m.On("Get", mock.Anything, constants.RedisAuthTokenKey("timeout-token")).Return(getCmd)
},
wantUser: "",
wantErr: true,
},
{
name: "empty token",
token: "",
setupMock: func(m *MockRedisClient) {
// Mock Ping success
pingCmd := redis.NewStatusCmd(context.Background())
pingCmd.SetVal("PONG")
m.On("Ping", mock.Anything).Return(pingCmd)
// Mock Get returns redis.Nil for empty token
getCmd := redis.NewStringCmd(context.Background())
getCmd.SetErr(redis.Nil)
m.On("Get", mock.Anything, constants.RedisAuthTokenKey("")).Return(getCmd)
},
wantUser: "",
wantErr: true,
errType: errors.ErrInvalidToken,
},
{
name: "Redis returns empty user ID",
token: "invalid-user-token",
setupMock: func(m *MockRedisClient) {
// Mock Ping success
pingCmd := redis.NewStatusCmd(context.Background())
pingCmd.SetVal("PONG")
m.On("Ping", mock.Anything).Return(pingCmd)
// Mock Get returns empty string
getCmd := redis.NewStringCmd(context.Background())
getCmd.SetVal("")
m.On("Get", mock.Anything, constants.RedisAuthTokenKey("invalid-user-token")).Return(getCmd)
},
wantUser: "",
wantErr: true,
errType: errors.ErrInvalidToken,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Create mock Redis client
mockRedis := new(MockRedisClient)
if tt.setupMock != nil {
tt.setupMock(mockRedis)
}
// Create validator with mock
validator := NewTokenValidator(mockRedis, zap.NewNop())
// Call Validate
userID, err := validator.Validate(tt.token)
// Assert results
if tt.wantErr {
assert.Error(t, err, "Expected error for test case: %s", tt.name)
if tt.errType != nil {
assert.ErrorIs(t, err, tt.errType, "Expected specific error type for test case: %s", tt.name)
}
} else {
assert.NoError(t, err, "Expected no error for test case: %s", tt.name)
}
assert.Equal(t, tt.wantUser, userID, "User ID mismatch for test case: %s", tt.name)
// Assert all expectations were met
mockRedis.AssertExpectations(t)
})
}
}
// TestTokenValidator_IsAvailable tests the Redis availability check
func TestTokenValidator_IsAvailable(t *testing.T) {
tests := []struct {
name string
setupMock func(*MockRedisClient)
want bool
}{
{
name: "Redis is available",
setupMock: func(m *MockRedisClient) {
pingCmd := redis.NewStatusCmd(context.Background())
pingCmd.SetVal("PONG")
m.On("Ping", mock.Anything).Return(pingCmd)
},
want: true,
},
{
name: "Redis is unavailable",
setupMock: func(m *MockRedisClient) {
pingCmd := redis.NewStatusCmd(context.Background())
pingCmd.SetErr(context.DeadlineExceeded)
m.On("Ping", mock.Anything).Return(pingCmd)
},
want: false,
},
{
name: "Redis connection refused",
setupMock: func(m *MockRedisClient) {
pingCmd := redis.NewStatusCmd(context.Background())
pingCmd.SetErr(assert.AnError)
m.On("Ping", mock.Anything).Return(pingCmd)
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Create mock Redis client
mockRedis := new(MockRedisClient)
if tt.setupMock != nil {
tt.setupMock(mockRedis)
}
// Create validator with mock
validator := NewTokenValidator(mockRedis, zap.NewNop())
// Call IsAvailable
available := validator.IsAvailable()
// Assert result
assert.Equal(t, tt.want, available, "Availability mismatch for test case: %s", tt.name)
// Assert all expectations were met
mockRedis.AssertExpectations(t)
})
}
}
// TestTokenValidator_ValidateWithRealTimeout tests with actual context timeout
func TestTokenValidator_ValidateWithRealTimeout(t *testing.T) {
// This test verifies that the validator uses a 50ms timeout internally
// We test this by simulating a timeout error from Redis
mockRedis := new(MockRedisClient)
// Mock Ping success
pingCmd := redis.NewStatusCmd(context.Background())
pingCmd.SetVal("PONG")
mockRedis.On("Ping", mock.Anything).Return(pingCmd)
// Mock Get with timeout error
getCmd := redis.NewStringCmd(context.Background())
getCmd.SetErr(context.DeadlineExceeded)
mockRedis.On("Get", mock.Anything, mock.Anything).Return(getCmd)
// Create validator with mock
validator := NewTokenValidator(mockRedis, zap.NewNop())
// Call Validate (should return timeout error)
userID, err := validator.Validate("timeout-token")
// Should get timeout error
assert.Error(t, err)
assert.Equal(t, "", userID)
assert.ErrorIs(t, err, context.DeadlineExceeded)
mockRedis.AssertExpectations(t)
}