在生产包使用上测试 golang 分析器

Test golang analyzer on production package usage

我有一个模块 errs 定义了一个 MultiError 像这样:

type MultiError []error
func NewMultiError(errs ...error) MultiError {}
// implementation omitted

我想测试一个 Go 分析器,要求 MultiError 总是由 errs.NewMultiError() 创建,而不是使用复合结构文字 errs.MultiError{}。编写分析器本身很简单。

func run(pass *analysis.Pass) (interface{}, error) {
    for _, f := range pass.Files {
        ast.Inspect(f, func(n ast.Node) bool {
            if l, ok := n.(*ast.CompositeLit); ok {
                // Assume this does the right thing.
                return checkCompositeLit(l, pass)
            }
            return true
        })
    }
    return nil, nil
}

我尝试过的方法是在 testdata 下使用伪造的 errs 包创建一个源代码树。我更愿意使用真正的 errs 包,但我不知道如何使用:

源代码树:

.
├── multi_error.go
├── multi_error_test.go
└── testdata
    └── src
        ├── errs
        │   └── errs.go
        └── p
            └── p.go

但是 analysistest 似乎进行了部分包加载,所以我无法依赖 p.

包中的存根 errs
// testdata/src/p/p.go
package p

import (
    "fmt"
)


func foo() {
    me := errs.MultiError{} // want `found MultiError created from struct literal; use errs.NewMultiError\(\) instead`
    me2 := errs.NewMultiError()

    fmt.Print(me, me2)
}

如何测试分析仪?是否可以使用真正的 errs 包而不是存根进行测试?

解决方法是将 import "errs" 添加到 testdata/src/p/p.go。然后修改 analysistest.Run 中的模式以包含 testdata、errsp 下的包。 analysistest 将正确连接包。

func TestAll(t *testing.T) {
    analysistest.Run(t, analysistest.TestData(), Analyzer, "p", "errs")
}