【问题标题】:How to share test interfaces between Go packages?如何在 Go 包之间共享测试接口?
【发布时间】:2017-05-26 21:50:55
【问题描述】:

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

使用testing/quick的示例:

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

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) 范围内的Things:

$ 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.gobar_test.go 不可用,所以quick.Value() 不使用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(或任何其他带有接口的测试库)?

【问题讨论】:

    标签: testing go quickcheck property-testing


    【解决方案1】:

    包之间共享的任何代码都必须在非测试文件中。但这并不意味着它必须包含在任何最终版本中。您可以使用build constraints 从正常构建中排除文件,并使用build tags 在运行测试时包含它们。例如,您可以将共享的测试代码放在前缀为:

    的文件中
    //+build testtools
    
    package mypackage
    

    (但 命名为 _test.go)。构建时,它不会包含在构建中。当你测试时,你会使用类似的东西:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-21
      • 2020-09-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多