如何在多个包中使用通用测试套件?

Dou*_*oug 9 go

当我编写接口时,通常可以方便地在与接口相同的包中定义我的测试,然后定义实现接口集的多个包,例如.

package/
package/impl/x <-- Implementation X
package/impl/y <-- Implementation Y
Run Code Online (Sandbox Code Playgroud)

有没有一种简单的方法可以在子包中运行相同的测试套件(在本例中,位于package/*_ test.go中)?

我到目前为止提出的最佳解决方案是添加一个测试包:

package/tests/
Run Code Online (Sandbox Code Playgroud)

它实现了测试套件,并在每个实现中进行测试以运行测试,但这有两个缺点:

1)包/测试中的测试不在_test.go文件中,最终成为实际库的一部分,由godoc等记录.

2)包/测试中的测试由自定义测试运行器运行,该测试运行器必须基本上复制'go test'的所有功能以扫描go测试并运行它们.

看起来像一个非常俗气的解决方案.

有没有更好的方法呢?

fuz*_*fuz 7

我真的不喜欢使用单独的测试库.如果您有一个接口,并且每个接口都有通用测试,那么实现该接口的其他人也可能希望使用这些测试.

您可以创建"package/test"包含函数的包

// functions needed for each implementation to test it
type Tester struct {
    func New() package.Interface
    func (*package.Interface) Done()
    // whatever you need. Leave nil if function does not apply
}

func TestInterface(t *testing.T, tester Tester)
Run Code Online (Sandbox Code Playgroud)

请注意,签名TestInterfacego test期望的不匹配.现在,为每个包package/impl/x添加一个文件generic_test.go:

package x

import "testing"
import "package/test"

// run generic tests on this particular implementation
func TestInterface(t *testing.T) {
    test.TestInterface(t,test.Tester{New:New})
}
Run Code Online (Sandbox Code Playgroud)

New()您的实现的构造函数在哪里.这种方案的优点是

  1. 您的测试可以重复用于实现您的界面的人,甚至是其他包
  2. 很明显,您运行通用测试套件
  3. 测试用例是实现的地方而不是另一个不起眼的地方
  4. 如果一个实现需要特殊的初始化或类似的东西,可以很容易地调整代码
  5. 它是go test兼容的(大加!)

当然,在某些情况下,您需要更复杂的TestInterface功能,但这是基本的想法.