如何在Go软件包之间共享测试接口? [英] How to share test interfaces between Go packages?

查看:63
本文介绍了如何在Go软件包之间共享测试接口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Go不会在不同软件包的测试文件之间共享代码,因此不会自动重用测试接口的定义.在实践中我们如何解决这个问题?

Go doesn't share code between test files of different packages, so definitions of test interfaces aren't automatically reused. How can we work around this in practice?

foo/foo.go :

package foo

type Thing int

const (
  X Thing = iota
  Y
  Z
)

bar/bar.go :

package bar

import (
  "foo"
)

type Box struct {
  Thing foo.Thing
}

我们要对 foo 进行属性测试,因此我们在 Thing 上定义 testing/quick.Generate :

We want to property test foo, so we define testing/quick.Generate on Thing:

foo_test.go :

package foo

import (
  "math/rand"
  "reflect"
  "testing"
  "testing/quick"
  "time"
)

func (_ Thing) Generate(r *rand.Rand, sz int) reflect.Value {
  return reflect.ValueOf(Thing(r.Intn(3)))
}

func TestGenThing(t *testing.T) {
  r := rand.New(rand.NewSource(time.Now().UTC().UnixNano()))
  for i := 0; i < 5; i++ {
    val, _ := quick.Value(reflect.TypeOf(Thing(0)), r)
    tng, _ := val.Interface().(Thing)
    t.Logf("%#v\n", tng)
  }
}

quick.Value 返回预期范围在[0,3)范围内的 Thing :

quick.Value returns Things in the range [0,3) as expected:

$ go test -v foo
=== RUN   TestGenThing
--- PASS: TestGenThing (0.00s)
        foo_test.go:20: 0
        foo_test.go:20: 1
        foo_test.go:20: 2
        foo_test.go:20: 1
        foo_test.go:20: 2
PASS
ok      foo     0.026s

让我们的属性也测试 bar :

package bar

import (
  "math/rand"
  "reflect"
  "testing"
  "testing/quick"
  "time"

  "foo"
)

func (_ Box) Generate(r *rand.Rand, sz int) reflect.Value {
  val, _ := quick.Value(reflect.TypeOf(foo.Thing(0)), r)
  tng, _ := val.Interface().(foo.Thing)
  return reflect.ValueOf(Box{tng})
}

func TestGenBox(t *testing.T) {
  r := rand.New(rand.NewSource(time.Now().UTC().UnixNano()))
  for i := 0; i < 5; i++ {
    val, _ := quick.Value(reflect.TypeOf(Box{}), r)
    box, _ := val.Interface().(Box)
    t.Logf("%#v\n", box)
  }
}

但是 Box.Generate 已损坏. foo_test.go bar_test.go 不可用,因此 quick.Value()不使用 Thing.Generate():

But Box.Generate is broken. foo_test.go isn't available to bar_test.go, so quick.Value() doesn't use Thing.Generate():

$ GOPATH=$PWD go test -v bar
=== RUN   TestGenBox
--- PASS: TestGenBox (0.00s)
        bar_test.go:24: bar.Box{Thing:3919143124849004253}
        bar_test.go:24: bar.Box{Thing:-3486832378211479055}
        bar_test.go:24: bar.Box{Thing:-3056230723958856466}
        bar_test.go:24: bar.Box{Thing:-847200811847403542}
        bar_test.go:24: bar.Box{Thing:-2593052978030148925}
PASS
ok      bar     0.095s

是否有解决方法?人们在实践中如何使用 testing/quick (或任何其他具有接口的测试库)?

Is there a workaround for this? How do folks use testing/quick (or any other testing library with interfaces) in practice?

推荐答案

包之间共享的任何代码都必须位于非测试文件中.但是,这并不意味着它必须包含在任何最终版本中.您可以使用构建约束将文件从常规构建中排除,然后<一个href ="https://golang.org/cmd/go/#hdr-Compile_packages_and_dependencies" rel ="nofollow noreferrer">构建标记,以便在运行测试时将其包括在内.例如,您可以将共享的测试代码放在带有以下前缀的文件中:

Any code shared between packages must be in a non-test file. That doesn't mean it has to be included in any final builds though; you can use build constraints to exclude the files from normal builds, and build tags to include them when running tests. For example, you can put your shared test code in a file prefixed with:

//+build testtools

package mypackage

(但 not 名为_test.go).构建时,它不会包含在构建中.测试时,您将使用类似以下内容的

(but not named _test.go). When you build, this will not be included in the build. When you test, you'd use something like:

go test -tags "testtools" ./...

这将在构建中包含受约束的文件,从而使共享代码可用于测试.

This would include the constrained file in the build, and thereby make the shared code available to the tests.

这篇关于如何在Go软件包之间共享测试接口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆