尝试使用golang的testify/suite在并行中运行测试失败。

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

Trying to run tests in parallel with golang testify/suite fails

问题

我有几个使用testify/suite包的测试,并且按照以下方式并行执行:

type IntegrationSuite struct {
	suite.Suite
}

func TestIntegrationSuite(t *testing.T) {
	suite.Run(t, &IntegrationSuite{})
}

func (is *IntegrationSuite) TestSomething() {
	is.T().Log("\tIntegration Testing something")
	for i := range myTestTable {
		i := i
		is.T().Run("Testing "+myTestTable[i].scenarioName, func(_ *testing.T) {
			is.T().Parallel()
			...
		})
	}
}

func (is *IntegrationSuite) TestSomethingElse() {
	is.T().Log("\tIntegration Testing something else")
	for i := range myOtherTestTable {
		i := i
		is.T().Run("Testing "+myOtherTestTable[i].scenarioName, func(_ *testing.T) {
			is.T().Parallel()
			...
		})
	}
}

然而,这会导致以下错误:

panic: testing: t.Parallel called multiple times [recovered]
        panic: testing: t.Parallel called multiple times

如何在这个特定的包中利用并行性呢?

英文:

I have several tests using testify/suite package and I execute them in parallel as follows


type IntegrationSuite struct {
	suite.Suite
}

func TestIntegrationSuite(t *testing.T) {
	suite.Run(t, &IntegrationSuite{})
}

func (is *IntegrationSuite) TestSomething() {
	is.T().Log("\tIntegration Testing something")
	for i := range myTestTable {
		i := i
		is.T().Run("Testing "+myTestTable[i].scenarioName, func(_ *testing.T) {
			is.T().Parallel()
...

func (is *IntegrationSuite) TestSomethingElse() {
	is.T().Log("\tIntegration Testing something else")
	for i := range myOtherTestTable {
		i := i
		is.T().Run("Testing "+myOtherTestTable[i].scenarioName, func(_ *testing.T) {
			is.T().Parallel()
...
		})

However this panics with

panic: testing: t.Parallel called multiple times [recovered]
        panic: testing: t.Parallel called multiple times

How can one leverage parallelism with the specific package?

答案1

得分: 1

你正在对错误的 testing.T 实例调用 t.Parallel()

你正在使用以下方式启动多个子测试

is.T().Run("Testing "+myOtherTestTable[i].scenarioName, func(_ *testing.T) {...}

但是,你没有将子测试标记为并行,而是将外部父测试标记为并行,对于每个启动的子测试都是如此:

is.T().Parallel() // 将外部测试标记为并行

相反,将子测试函数的 testing.T 参数绑定到一个变量,并在子测试上调用 Parallel

is.T().Run("Testing "+myOtherTestTable[i].scenarioName, func(t *testing.T) {
    t.Parallel() // 这是子测试的 T 实例
    // 测试代码
})

这将在父测试中将所有子测试标记为并行。如果你还想将父测试与包中的其他测试标记为并行,请在 TestSomethingElse 的开头调用 is.T().Parallel() 一次(不要在子测试中调用)。

有关子测试并行性的更多详细信息,请参阅:并行控制

英文:

You're calling t.Parallel() on the wrong instance of testing.T.

You're spinning up multiple subtests using:

is.T().Run("Testing "+myOtherTestTable[i].scenarioName, func(_ *testing.T) {...}

But instead of marking the subtest as parallel, you're marking the outer parent test as parallel for every subtest you start:

is.T().Parallel() // marks outer test as parallel

Instead, bind the subtest func's testing.T param to a variable and call Parallel on the subtest:

        is.T().Run("Testing "+myOtherTestTable[i].scenarioName, func(t *testing.T) {
            t.Parallel() // this is the subtest's T instance
            // test code
        })

This marks all subtests as parallel within the parent test. If you also want to mark the parent test as parallel with other tests in the package, call is.T().Parallel() once at the beginning of TestSomethingElse (not within the subtest)

For more details on parallelism of subtests, see: Control of Parallelism

答案2

得分: 0

请注意,目前的测试套件不是“线程安全”的,因此不支持并发。有些情况下,即使测试应该失败,但测试仍然成功通过。

请在此处查看当前状态以及报告的问题:https://github.com/stretchr/testify/issues/187

英文:

Please note that the testify suite is currently not "thread safe" and therefore does not support concurrency. There are cases in which tests pass successfully even though they should fail.

Please find the current status as well the reported issues here: https://github.com/stretchr/testify/issues/187

huangapple
  • 本文由 发表于 2022年8月16日 23:53:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/73376842.html
匿名

发表评论

匿名网友

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

确定