恐慌:测试:在初始化之前调用了Verbose

huangapple go评论82阅读模式
英文:

panic: testing: Verbose called before Init

问题

尝试运行 https://github.com/adonovan/gopl.io/blob/master/ch8/cake/cake_test.go,但是出现了以下错误:

panic: testing: Verbose called before Init

goroutine 1 [running]:
testing.Verbose(...)
  /usr/lib/go-1.17/src/testing/testing.go:453
.../cake_test.init()

错误显示来自 cake_test.init(),但是 cake_test.go 文件中并没有包含 init() 函数:

$ grep init cake_test.go | wc
      0       0       0

请问问题出在哪里?

英文:

Trying to run
https://github.com/adonovan/gopl.io/blob/master/ch8/cake/cake_test.go

but got

panic: testing: Verbose called before Init

goroutine 1 [running]:
testing.Verbose(...)
  /usr/lib/go-1.17/src/testing/testing.go:453
.../cake_test.init()

It says the error comes from cake_test.init(), yet the cake_test.go file doesn't contain init():

$ grep init cake_test.go | wc
      0       0       0

What exactly is the problem?

答案1

得分: 2

这是因为测试包本身有一个init函数来处理测试标志,并且你调用了Verbose来创建一个全局变量。

为了避免这个问题,你可以尝试以下方法:

  1. 使用函数指针来捕获testing.Verbose,并在所有初始化之后的函数中使用它(Verbose的类型将是func() bool),但我认为这种方法比较复杂。
  2. 添加一个辅助函数,在每个测试中创建一个新的默认值,并安全地调用testing.Verbose。
  3. 创建一个构造函数(而不是测试辅助函数),用最常见的选项填充,并在每个测试中设置Verbose的值。
  4. 创建两个构造函数,第二个构造函数接收Verbose的值作为参数。

另外,考虑创建一个名为Debug的方法,与Println具有相同的签名,如果Verbose为true,则调用fmt.Println。

如果你有一个构造函数,你可以创建一个第二个字段:Logger,它是一个与Println具有相同签名的函数指针,并将其初始化为fmt.Println,在测试中你可以将其设置为t.Log,以获得更好的体验。

当然,也许有些建议比其他建议更高级,你可以自由尝试并选择最好的方法。

英文:

This happens because the testing package itself has a init to process test flags and you are callind Verbose to create a global variable

https://cs.opensource.google/go/go/+/refs/tags/go1.18:src/testing/testing.go;l=548

To avoid this you can:

  1. Use a ponter to function to capture testing.Verbose and use inside functions, after all initializations ( Verbose will be type func() bool) but I think this is complex
  2. Add a helper that creates a new default on each test with a safe call to testing.Verbose
  3. Create a constructor (instead a test helper) that fill with the most common options and you can set the value of Verbose on each test
  4. Create a two constructors, a second one that receive the value of Verbose

Also, Consider create a method Debug with same signature of Println, to call fmt.Println if Verbose is true

If you have a constructor, you can create a second field: Logger, with is a ponter to function with same signature as Println and you initialize with fmt.Println and in the tests you can set as t.Log to have a better experience

Of course perhaps some suggestions are more advanced than others, feel free to play a little bit and choose the best ones

答案2

得分: 2

对于这个特定的情况,添加Init()函数就解决了问题。

var defaults cake.Shop

func Init() {
	defaults = cake.Shop{
		Verbose:      testing.Verbose(),
		Cakes:        20,
		BakeTime:     10 * time.Millisecond,
		NumIcers:     1,
		IceTime:      10 * time.Millisecond,
		InscribeTime: 10 * time.Millisecond,
	}
}
英文:

For this specific case, adding Init() function did the trick.

var defaults cake.Shop

func Init() {
	defaults = cake.Shop{
		Verbose:      testing.Verbose(),
		Cakes:        20,
		BakeTime:     10 * time.Millisecond,
		NumIcers:     1,
		IceTime:      10 * time.Millisecond,
		InscribeTime: 10 * time.Millisecond,
	}
}

huangapple
  • 本文由 发表于 2022年3月27日 11:51:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/71633561.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定