首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >用 AST 自动提取 Go 方法的业务规则:让 AI 看懂你的 if-else

用 AST 自动提取 Go 方法的业务规则:让 AI 看懂你的 if-else

作者头像
沈宥
发布2026-04-14 18:17:43
发布2026-04-14 18:17:43
360
举报

摘要 你是否希望:

  • 开发改了一段 Go 代码,AI 就能自动知道“新增了什么业务逻辑”?
  • 不用手写文档,系统就能生成精准的测试用例和回归范围?

关键在于:让机器理解代码中的业务语义。 本文手把手教你用 Go 官方 go/ast,从真实 Go 函数中自动提取: ✅ 条件分支(if/else) ✅ 业务规则(如 “VIP 用户免运费”) ✅ 返回值逻辑 ✅ 关键依赖调用 所有代码 100% 本地运行,无需外部服务,输出结构化 JSON,可直接喂给 LLM 生成测试用例。


一、为什么需要从 AST 提取业务规则?

很多团队尝试用 AI 生成测试,但效果不佳,原因往往是:

**AI 只看到代码文本,看不懂“业务意图”**。

例如这段 Go 代码:

go编辑

代码语言:javascript
复制
func NeedCaptcha(phone string) bool {
    if phone == "" {
        return true
    }
    member, _ := memberRepo.GetByPhone(phone)
    if member != nil && member.IsVIP {
        return false // VIP 免验证码
    }
    return true
}

人类一眼看出三条规则:

  1. 手机号为空 → 需验证码
  2. 是 VIP 会员 → 免验证码
  3. 其他情况 → 需验证码

但普通 LLM 可能只生成:“测试空字符串、非空字符串”——漏掉 VIP 这个关键业务概念

AST 解析 能精准捕获:

  • if 条件中的 member.IsVIP
  • return false 的上下文
  • memberRepo.GetByPhone 的依赖

💡 **AST = 代码的“骨骼”**,比正则或字符串匹配更可靠。


二、Go AST 基础:三分钟入门

Go 标准库 go/astgo/parser 可将源码转为树形结构。

关键节点类型:

表格

代码语言:javascript
复制
函数声明

我们只需遍历这棵树,提取关键信息。


三、实战:编写 AST 规则提取器

步骤 1:准备示例 Go 文件(user_service.go

go编辑

代码语言:javascript
复制
package service

import "your-project/repo"

type UserService struct {
    memberRepo repo.MemberRepo
}

// NeedCaptcha 判断是否需要图形验证码
// 业务规则:
// - 手机号为空:需要
// - 已注册 VIP 会员:不需要
// - 其他:需要
func (s *UserService) NeedCaptcha(phone string) bool {
    if phone == "" {
        return true
    }
    member, err := s.memberRepo.GetByPhone(phone)
    if err != nil {
        return true // 查询失败视为新用户
    }
    if member != nil && member.IsVIP {
        return false
    }
    return true
}

步骤 2:编写 AST 解析脚本(extract_rules.go

go编辑

代码语言:javascript
复制
func main() {
    // 输出结构化规则
    fmt.Printf("Extracted rules for %s:\n", rules.Name)
    for i, r := range rules.Rules {
        fmt.Printf("%d. IF %s → %s\n", i+1, r.Condition, r.Action)
        if len(r.Calls) > 0 {
            fmt.Printf("   Calls: %v\n", r.Calls)
        }
    }
}

func extractRulesFromFunc(fn *ast.FuncDecl) []Rule {
    // 遍历函数体
    ast.Inspect(fn.Body, func(n ast.Node) bool {
        switch x := n.(type) {
        case *ast.CallExpr:
            // 记录函数调用,如 s.memberRepo.GetByPhone
            if sel, ok := x.Fun.(*ast.SelectorExpr); ok {
                callStr := fmt.Sprintf("%s.%s", exprToString(sel.X), sel.Sel.Name)
                currentCalls = append(currentCalls, callStr)
            }

        case *ast.IfStmt:
            // 检查 Then 分支是否有 return
            if ret, ok := hasReturn(x.Body); ok {
                action = ret
            }
        return true
    })

    return rules
}

步骤 3:运行!看 AI 如何“读懂”你的代码

bash编辑

代码语言:javascript
复制
go run extract_rules.go

输出结果

文本编辑

代码语言:javascript
复制
Extracted rules for NeedCaptcha:
1. IF phone == "" → true
2. IF err != nil → true
   Calls: [s.memberRepo.GetByPhone]
3. IF member != nil && member.IsVIP → false
   Calls: [s.memberRepo.GetByPhone]
4. IF default → true
   Calls: [s.memberRepo.GetByPhone]

完美捕获所有业务分支! ✅ 识别出关键字段 member.IsVIP记录依赖调用 s.memberRepo.GetByPhone


四、进阶:将规则注入 LLM,生成精准测试

将上述 JSON 结构喂给本地 LLM(如 Ollama Qwen):

json编辑

代码语言:javascript
复制
{
  "name": "NeedCaptcha",
  "rules": [
    {"condition": "phone == \"\"", "action": "true"},
    {"condition": "err != nil", "action": "true", "calls": ["s.memberRepo.GetByPhone"]},
    {"condition": "member != nil && member.IsVIP", "action": "false", "calls": ["s.memberRepo.GetByPhone"]},
    {"condition": "default", "action": "true"}
  ]
}

Prompt 示例:

“你是一名 QA,请为 NeedCaptcha 函数生成 Go 单元测试,覆盖所有规则。使用 testify/mock mock memberRepo。”

LLM 将输出:

go编辑

代码语言:javascript
复制
func TestNeedCaptcha(t *testing.T) {
    // Case 1: empty phone
    assert.True(t, svc.NeedCaptcha(""))

    // Case 2: repo error
    mockRepo.On("GetByPhone", "138...").Return(nil, errors.New("db error"))
    assert.True(t, svc.NeedCaptcha("138..."))

    // Case 3: VIP member
    mockRepo.On("GetByPhone", "139...").Return(&Member{IsVIP: true}, nil)
    assert.False(t, svc.NeedCaptcha("139..."))

    // Case 4: normal user
    mockRepo.On("GetByPhone", "137...").Return(&Member{IsVIP: false}, nil)
    assert.True(t, svc.NeedCaptcha("137..."))
}

业务规则 → 测试用例,全自动


五、落地建议

  1. 集成到 CI:每次 MR 提交,自动解析变更函数,输出规则差异。
  2. 结合注释:在 Go 注释中写 // @rule VIP 用户免验证码,AST 可一并提取。
  3. 扩展支持:增加对 switchfor、错误处理的解析。
  4. 构建知识库:将提取结果存入数据库,形成接口知识图谱。

结语:AST,是 AI 理解代码的“翻译器”

不要让 AI 猜你的业务逻辑, 而是用 AST 把逻辑“翻译”成它能懂的语言

通过 AST 自动提取 Go 方法的业务规则, 你不仅提升了测试效率,更在构建 AI 原生的质量基础设施

现在,就去跑一遍你的核心函数—— 看看 AI 能不能真正“读懂”你的 if-else


作者:Go 语言质量工程师 环境:Go 1.22 + 标准库 go/ast 完整代码:https://github.com/shemiouwang-lgtm/go-ast-rule-extractor.git

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-04-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 质量工程与测开技术栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、为什么需要从 AST 提取业务规则?
  • 二、Go AST 基础:三分钟入门
  • 三、实战:编写 AST 规则提取器
    • 步骤 1:准备示例 Go 文件(user_service.go)
    • 步骤 2:编写 AST 解析脚本(extract_rules.go)
    • 步骤 3:运行!看 AI 如何“读懂”你的代码
  • 四、进阶:将规则注入 LLM,生成精准测试
  • 五、落地建议
  • 结语:AST,是 AI 理解代码的“翻译器”
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档