测试生成

wescode 利用 AI 和代码知识图谱自动生成高质量的测试代码,支持单元测试、集成测试和边界用例,并提供覆盖率分析和 TDD 工作流支持。

单元测试

自动生成

选中函数或在 Chat 面板中指定目标即可生成单元测试:

# 为当前文件生成测试
/test generate

# 为指定函数生成测试
/test generate --func ParseConfig

# 为指定文件生成测试
/test generate internal/service/user.go

生成策略

wescode 生成测试时会分析:

  1. 函数签名:输入参数类型和返回值类型
  2. 函数逻辑:条件分支、循环、错误路径
  3. 依赖关系:外部依赖自动生成 Mock
  4. 调用上下文:通过 CKG 分析实际调用方式
  5. 项目约定:遵循项目已有的测试风格

生成示例

对于以下 Go 函数:

func ParseDuration(s string) (time.Duration, error) {
    if s == "" {
        return 0, fmt.Errorf("empty duration string")
    }
    return time.ParseDuration(s)
}

wescode 会生成:

func TestParseDuration(t *testing.T) {
    tests := []struct {
        name    string
        input   string
        want    time.Duration
        wantErr bool
    }{
        {
            name:  "valid duration seconds",
            input: "30s",
            want:  30 * time.Second,
        },
        {
            name:  "valid duration minutes",
            input: "5m",
            want:  5 * time.Minute,
        },
        {
            name:    "empty string",
            input:   "",
            wantErr: true,
        },
        {
            name:    "invalid format",
            input:   "abc",
            wantErr: true,
        },
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            got, err := ParseDuration(tt.input)
            if tt.wantErr {
                require.Error(t, err)
                return
            }
            require.NoError(t, err)
            assert.Equal(t, tt.want, got)
        })
    }
}

测试风格适配

wescode 会自动识别并匹配项目的测试风格:

检测项示例
测试框架testing / testify / gomega
命名风格TestXxx / Test_xxx
组织方式表驱动测试 / 独立用例
Assert 库assert / require / 标准库
Mock 方式gomock / testify/mock / 手写

集成测试

生成集成测试

对于涉及数据库、HTTP 或外部服务的代码:

# 生成 HTTP handler 集成测试
/test generate --type integration internal/handler/user.go

# 生成数据库操作集成测试
/test generate --type integration internal/repo/user.go

测试基础设施

wescode 会根据需要自动生成测试辅助代码:

集成测试示例

func TestUserHandler_Create(t *testing.T) {
    // 设置测试数据库
    db := setupTestDB(t)
    defer db.Close()

    // 初始化依赖
    repo := NewUserRepository(db)
    svc := NewUserService(repo)
    handler := NewUserHandler(svc)

    // 创建测试服务器
    router := setupRouter(handler)
    srv := httptest.NewServer(router)
    defer srv.Close()

    // 执行测试
    body := `{"name": "Alice", "email": "alice@example.com"}`
    resp, err := http.Post(srv.URL+"/users", "application/json",
        strings.NewReader(body))

    require.NoError(t, err)
    assert.Equal(t, http.StatusCreated, resp.StatusCode)

    // 验证数据库状态
    user, err := repo.GetByEmail(context.Background(), "alice@example.com")
    require.NoError(t, err)
    assert.Equal(t, "Alice", user.Name)
}

测试覆盖

覆盖率分析

wescode 集成了测试覆盖率分析工具:

# 查看当前覆盖率
/test coverage

# 查看指定包的覆盖率
/test coverage internal/service/

# 查看未覆盖的代码行
/test coverage --uncovered

覆盖率可视化

覆盖率信息直接显示在编辑器中:

补充覆盖

针对未覆盖的代码自动生成补充测试:

# 为未覆盖的分支生成测试
/test fill-coverage internal/service/user.go

# 提升到目标覆盖率
/test fill-coverage --target 80%

覆盖率报告

覆盖率报告:internal/service/
┌─────────────────────┬──────┬──────┬──────┐
│ 文件                │ 语句 │ 分支 │ 函数 │
├─────────────────────┼──────┼──────┼──────┤
│ user.go             │ 85%  │ 72%  │ 90%  │
│ auth.go             │ 92%  │ 88%  │ 100% │
│ config.go           │ 65%  │ 50%  │ 80%  │
├─────────────────────┼──────┼──────┼──────┤
│ 总计                │ 81%  │ 70%  │ 90%  │
└─────────────────────┴──────┴──────┴──────┘

未覆盖的关键路径:
  config.go:45-52  错误处理分支
  config.go:78-85  默认值回退逻辑
  user.go:120-128  并发安全检查

边界用例

自动识别边界条件

wescode 通过代码分析自动识别需要测试的边界条件:

边界测试生成

# 生成边界用例
/test boundaries ParseConfig

# 生成模糊测试
/test fuzz ParseConfig

# 生成并发安全测试
/test concurrent UserCache

边界测试示例

func TestParseConfig_Boundaries(t *testing.T) {
    tests := []struct {
        name    string
        input   string
        wantErr bool
    }{
        {"nil input", "", true},
        {"whitespace only", "   \n\t  ", true},
        {"max length", strings.Repeat("a", 1<<20), true},
        {"unicode content", "配置=值", false},
        {"special chars", `key="val\"ue"`, false},
        {"duplicate keys", "key=1\nkey=2", true},
        {"circular reference", "a=${b}\nb=${a}", true},
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            _, err := ParseConfig([]byte(tt.input))
            if tt.wantErr {
                require.Error(t, err)
            } else {
                require.NoError(t, err)
            }
        })
    }
}

TDD 流程

TDD 模式

wescode 支持测试驱动开发工作流:

# 进入 TDD 模式
/tdd start

# 描述需求,AI 先生成测试
/tdd "实现一个 LRU 缓存,支持 Get、Put 和 TTL 过期"

TDD 工作流步骤

  1. Red(编写失败测试)

    • 根据需求描述生成测试用例
    • 运行测试确认失败(验证测试有效性)
  2. Green(编写最小实现)

    • AI 生成满足测试的最小实现代码
    • 运行测试确认通过
  3. Refactor(重构优化)

    • AI 建议可能的重构方向
    • 每次重构后自动运行测试确保不回退

TDD 示例会话

用户:/tdd "实现邮箱地址验证函数"

wescode:好的,开始 TDD 流程。

🔴 Step 1 - 生成测试:

  func TestValidateEmail(t *testing.T) {
      // 有效地址
      assert.True(t, ValidateEmail("user@example.com"))
      assert.True(t, ValidateEmail("user.name@domain.co"))
      // 无效地址
      assert.False(t, ValidateEmail(""))
      assert.False(t, ValidateEmail("user@"))
      assert.False(t, ValidateEmail("@domain.com"))
      assert.False(t, ValidateEmail("user domain.com"))
  }

  测试运行结果:FAIL(函数尚未实现)

🟢 Step 2 - 需要我生成实现代码吗?

持续测试

在 TDD 模式下,wescode 提供持续测试反馈:

配置选项

# .wescode/test.yaml
test:
  # 测试框架偏好
  framework: "testify"

  # 默认测试类型
  default-type: "unit"

  # Mock 生成方式
  mock-style: "gomock"

  # 覆盖率目标
  coverage-target: 80

  # 排除目录
  exclude:
    - "vendor/"
    - "*.generated.go"
    - "testdata/"

常见问题

Q: 生成的测试质量不高?

A: 确保 CKG 索引已完成,这样 AI 可以了解函数的实际使用模式。也可以在 Chat 中提供额外上下文来引导生成。

Q: Mock 生成不正确?

A: 检查接口定义是否完整。wescode 需要明确的接口定义来生成正确的 Mock。可以先用 /refactor extract-interface 提取接口。

Q: 如何处理需要外部服务的测试?

A: 使用 --type integration 标志,wescode 会自动使用 testcontainers 或 Mock 服务来处理外部依赖。