移除所有测试代码和测试要求
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m33s
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:
@@ -1,57 +0,0 @@
|
||||
package response
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
// BenchmarkSuccess 测试成功响应性能
|
||||
func BenchmarkSuccess(b *testing.B) {
|
||||
app := fiber.New()
|
||||
|
||||
b.Run("WithData", func(b *testing.B) {
|
||||
data := map[string]interface{}{
|
||||
"id": "123",
|
||||
"name": "测试用户",
|
||||
"age": 25,
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
ctx := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
_ = Success(ctx, data)
|
||||
app.ReleaseCtx(ctx)
|
||||
}
|
||||
})
|
||||
|
||||
b.Run("NoData", func(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
ctx := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
_ = Success(ctx, nil)
|
||||
app.ReleaseCtx(ctx)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// BenchmarkError 基准测试已被删除 - Error() 函数已在重构中移除
|
||||
// 错误响应现在由全局 ErrorHandler 统一处理
|
||||
|
||||
// BenchmarkSuccessWithMessage 测试带自定义消息的成功响应性能
|
||||
func BenchmarkSuccessWithMessage(b *testing.B) {
|
||||
app := fiber.New()
|
||||
|
||||
data := map[string]interface{}{
|
||||
"id": "123",
|
||||
"name": "测试用户",
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
ctx := app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
_ = SuccessWithMessage(ctx, data, "操作成功")
|
||||
app.ReleaseCtx(ctx)
|
||||
}
|
||||
}
|
||||
@@ -1,378 +0,0 @@
|
||||
package response
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
"github.com/bytedance/sonic"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
// TestSuccess 测试成功响应(T034)
|
||||
func TestSuccess(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
data any
|
||||
}{
|
||||
{
|
||||
name: "success with string data",
|
||||
data: "test data",
|
||||
},
|
||||
{
|
||||
name: "success with map data",
|
||||
data: map[string]any{
|
||||
"id": 123,
|
||||
"name": "test",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "success with slice data",
|
||||
data: []string{"item1", "item2", "item3"},
|
||||
},
|
||||
{
|
||||
name: "success with struct data",
|
||||
data: struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}{
|
||||
ID: 456,
|
||||
Name: "test struct",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "success with nil data",
|
||||
data: nil,
|
||||
},
|
||||
{
|
||||
name: "success with empty map",
|
||||
data: map[string]any{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
app := fiber.New()
|
||||
app.Get("/test", func(c *fiber.Ctx) error {
|
||||
return Success(c, tt.data)
|
||||
})
|
||||
|
||||
req := httptest.NewRequest("GET", "/test", nil)
|
||||
resp, err := app.Test(req)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to execute request: %v", err)
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
// 验证 HTTP 状态码
|
||||
if resp.StatusCode != 200 {
|
||||
t.Errorf("Expected status code 200, got %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
// 验证响应头(Fiber 会自动添加 charset=utf-8)
|
||||
contentType := resp.Header.Get("Content-Type")
|
||||
if contentType != "application/json" && contentType != "application/json; charset=utf-8" {
|
||||
t.Errorf("Expected Content-Type application/json or application/json; charset=utf-8, got %s", contentType)
|
||||
}
|
||||
|
||||
// 解析响应体
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read response body: %v", err)
|
||||
}
|
||||
|
||||
var response Response
|
||||
if err := sonic.Unmarshal(body, &response); err != nil {
|
||||
t.Fatalf("Failed to unmarshal response: %v", err)
|
||||
}
|
||||
|
||||
// 验证响应结构
|
||||
if response.Code != errors.CodeSuccess {
|
||||
t.Errorf("Expected code %d, got %d", errors.CodeSuccess, response.Code)
|
||||
}
|
||||
|
||||
if response.Message != "success" {
|
||||
t.Errorf("Expected message 'success', got '%s'", response.Message)
|
||||
}
|
||||
|
||||
// 验证时间戳格式 RFC3339
|
||||
if _, err := time.Parse(time.RFC3339, response.Timestamp); err != nil {
|
||||
t.Errorf("Timestamp is not in RFC3339 format: %s", response.Timestamp)
|
||||
}
|
||||
|
||||
// 验证数据字段(如果不是 nil)
|
||||
if tt.data != nil {
|
||||
if response.Data == nil {
|
||||
t.Error("Expected data field to be non-nil")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestError 测试已被删除 - Error() 函数已在重构中移除
|
||||
// 错误响应现在由全局 ErrorHandler 统一处理
|
||||
// 相关测试已迁移到 pkg/errors/handler_test.go
|
||||
|
||||
// TestSuccessWithMessage 测试带自定义消息的成功响应(T034)
|
||||
func TestSuccessWithMessage(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
data any
|
||||
message string
|
||||
}{
|
||||
{
|
||||
name: "custom success message",
|
||||
data: map[string]any{
|
||||
"user_id": 123,
|
||||
},
|
||||
message: "User created successfully",
|
||||
},
|
||||
{
|
||||
name: "empty custom message",
|
||||
data: "test data",
|
||||
message: "",
|
||||
},
|
||||
{
|
||||
name: "chinese message",
|
||||
data: map[string]string{
|
||||
"status": "ok",
|
||||
},
|
||||
message: "操作成功",
|
||||
},
|
||||
{
|
||||
name: "long message",
|
||||
data: nil,
|
||||
message: "This is a very long success message that describes in detail what happened during the operation",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
app := fiber.New()
|
||||
app.Get("/test", func(c *fiber.Ctx) error {
|
||||
return SuccessWithMessage(c, tt.data, tt.message)
|
||||
})
|
||||
|
||||
req := httptest.NewRequest("GET", "/test", nil)
|
||||
resp, err := app.Test(req)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to execute request: %v", err)
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
// 验证 HTTP 状态码(默认 200)
|
||||
if resp.StatusCode != 200 {
|
||||
t.Errorf("Expected status code 200, got %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
// 解析响应体
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read response body: %v", err)
|
||||
}
|
||||
|
||||
var response Response
|
||||
if err := sonic.Unmarshal(body, &response); err != nil {
|
||||
t.Fatalf("Failed to unmarshal response: %v", err)
|
||||
}
|
||||
|
||||
// 验证响应结构
|
||||
if response.Code != errors.CodeSuccess {
|
||||
t.Errorf("Expected code %d, got %d", errors.CodeSuccess, response.Code)
|
||||
}
|
||||
|
||||
if response.Message != tt.message {
|
||||
t.Errorf("Expected message '%s', got '%s'", tt.message, response.Message)
|
||||
}
|
||||
|
||||
// 验证时间戳格式 RFC3339
|
||||
if _, err := time.Parse(time.RFC3339, response.Timestamp); err != nil {
|
||||
t.Errorf("Timestamp is not in RFC3339 format: %s", response.Timestamp)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestResponseSerialization 测试响应序列化(T036)
|
||||
func TestResponseSerialization(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
response Response
|
||||
}{
|
||||
{
|
||||
name: "complete response",
|
||||
response: Response{
|
||||
Code: 0,
|
||||
Data: map[string]any{"key": "value"},
|
||||
Message: "success",
|
||||
Timestamp: time.Now().Format(time.RFC3339),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "response with nil data",
|
||||
response: Response{
|
||||
Code: 1000,
|
||||
Data: nil,
|
||||
Message: "error",
|
||||
Timestamp: time.Now().Format(time.RFC3339),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "response with nested data",
|
||||
response: Response{
|
||||
Code: 0,
|
||||
Data: map[string]any{
|
||||
"user": map[string]any{
|
||||
"id": 123,
|
||||
"name": "test",
|
||||
"tags": []string{"tag1", "tag2"},
|
||||
},
|
||||
},
|
||||
Message: "success",
|
||||
Timestamp: time.Now().Format(time.RFC3339),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// 序列化
|
||||
data, err := sonic.Marshal(tt.response)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to marshal response: %v", err)
|
||||
}
|
||||
|
||||
// 反序列化
|
||||
var deserialized Response
|
||||
if err := sonic.Unmarshal(data, &deserialized); err != nil {
|
||||
t.Fatalf("Failed to unmarshal response: %v", err)
|
||||
}
|
||||
|
||||
// 验证字段
|
||||
if deserialized.Code != tt.response.Code {
|
||||
t.Errorf("Code mismatch: expected %d, got %d", tt.response.Code, deserialized.Code)
|
||||
}
|
||||
|
||||
if deserialized.Message != tt.response.Message {
|
||||
t.Errorf("Message mismatch: expected '%s', got '%s'", tt.response.Message, deserialized.Message)
|
||||
}
|
||||
|
||||
if deserialized.Timestamp != tt.response.Timestamp {
|
||||
t.Errorf("Timestamp mismatch: expected '%s', got '%s'", tt.response.Timestamp, deserialized.Timestamp)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestResponseStructFields 测试响应结构字段(T036)
|
||||
func TestResponseStructFields(t *testing.T) {
|
||||
response := Response{
|
||||
Code: 0,
|
||||
Data: "test",
|
||||
Message: "success",
|
||||
Timestamp: time.Now().Format(time.RFC3339),
|
||||
}
|
||||
|
||||
data, err := sonic.Marshal(response)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to marshal response: %v", err)
|
||||
}
|
||||
|
||||
// 解析为 map 以检查 JSON 键
|
||||
var jsonMap map[string]any
|
||||
if err := sonic.Unmarshal(data, &jsonMap); err != nil {
|
||||
t.Fatalf("Failed to unmarshal to map: %v", err)
|
||||
}
|
||||
|
||||
// 验证所有必需字段都存在
|
||||
requiredFields := []string{"code", "data", "msg", "timestamp"}
|
||||
for _, field := range requiredFields {
|
||||
if _, exists := jsonMap[field]; !exists {
|
||||
t.Errorf("Required field '%s' is missing in JSON response", field)
|
||||
}
|
||||
}
|
||||
|
||||
// 验证字段类型
|
||||
if _, ok := jsonMap["code"].(float64); !ok {
|
||||
t.Error("Field 'code' should be a number")
|
||||
}
|
||||
|
||||
if _, ok := jsonMap["msg"].(string); !ok {
|
||||
t.Error("Field 'msg' should be a string")
|
||||
}
|
||||
|
||||
if _, ok := jsonMap["timestamp"].(string); !ok {
|
||||
t.Error("Field 'timestamp' should be a string")
|
||||
}
|
||||
}
|
||||
|
||||
// TestMultipleResponses 测试多个连续响应(T036)
|
||||
func TestMultipleResponses(t *testing.T) {
|
||||
app := fiber.New()
|
||||
|
||||
callCount := 0
|
||||
app.Get("/test", func(c *fiber.Ctx) error {
|
||||
callCount++
|
||||
// 只返回成功响应,因为 Error() 函数已被删除
|
||||
return Success(c, map[string]int{"count": callCount})
|
||||
})
|
||||
|
||||
// 发送多个请求
|
||||
for i := 1; i <= 5; i++ {
|
||||
req := httptest.NewRequest("GET", "/test", nil)
|
||||
resp, err := app.Test(req)
|
||||
if err != nil {
|
||||
t.Fatalf("Request %d failed: %v", i, err)
|
||||
}
|
||||
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
_ = resp.Body.Close()
|
||||
|
||||
var response Response
|
||||
if err := sonic.Unmarshal(body, &response); err != nil {
|
||||
t.Fatalf("Request %d: failed to unmarshal response: %v", i, err)
|
||||
}
|
||||
|
||||
// 验证每个响应都有时间戳
|
||||
if response.Timestamp == "" {
|
||||
t.Errorf("Request %d: timestamp should not be empty", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestTimestampFormat 测试时间戳格式(T036)
|
||||
func TestTimestampFormat(t *testing.T) {
|
||||
app := fiber.New()
|
||||
app.Get("/test", func(c *fiber.Ctx) error {
|
||||
return Success(c, nil)
|
||||
})
|
||||
|
||||
req := httptest.NewRequest("GET", "/test", nil)
|
||||
resp, err := app.Test(req)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to execute request: %v", err)
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
var response Response
|
||||
if err := sonic.Unmarshal(body, &response); err != nil {
|
||||
t.Fatalf("Failed to unmarshal response: %v", err)
|
||||
}
|
||||
|
||||
// 验证是 RFC3339 格式
|
||||
parsedTime, err := time.Parse(time.RFC3339, response.Timestamp)
|
||||
if err != nil {
|
||||
t.Fatalf("Timestamp is not in RFC3339 format: %s, error: %v", response.Timestamp, err)
|
||||
}
|
||||
|
||||
// 验证时间戳是最近的(应该在最近 1 秒内)
|
||||
now := time.Now()
|
||||
diff := now.Sub(parsedTime)
|
||||
if diff < 0 || diff > time.Second {
|
||||
t.Errorf("Timestamp seems incorrect: %s (diff from now: %v)", response.Timestamp, diff)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user