如何解决死锁(等待来自失败测试的信号)

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

How to solve deadlock(waiting for singal from a failed test)

问题

我有两个goroutine,在测试期间分别是两个TestXxx函数。我使用一个条件变量来同步这些goroutine。然而,一旦其中一个测试失败,而另一个正在等待信号,就会出现死锁。此外,如果TestFunctionB失败,我希望TestFunctionA也失败。

我尝试了一些方法,例如:

var cond sync.Cond
func TestFunctionA(t *testing.T){
   // ... 一些代码...
   cond.Wait()
}
func TestFunctionB(t *testing.T){
   // ... 一些代码...
   t.Fail()
   // ... 一些代码...
   cond.Broadcast()
}

我尝试了以下方式:

var cond sync.Cond
var A_t *testing.T
func TestFunctionA(t *testing.T){
   // ... 一些代码...
   A_t = t
   // ... 一些代码...
   cond.Wait()
}
func TestFunctionB(t *testing.T){
   // ... 一些代码...
   t.Cleanup(func(){
      if !A_t.Failed(){
          A_t.Fail()
      }
      cond.Broadcast()
   })
   t.Fail()
   // ... 一些代码...
   cond.Broadcast()
}

但是,当FunctionB中没有错误时,A_t.Fail()仍然会触发。

我还在考虑使用context.Context(),但是我不知道如何在测试函数中使用它。

谢谢阅读我的问题!我欢迎任何评论或讨论!

英文:

I have two goroutines which are two TestXxx functions during the testing. I use a conditional variable to synchronize these goroutines. However, once one of them fails the test while the other one is waiting for the signal. Here comes a deadlock. Also, I want TestFunctionA to be failed if TestFunctionB is failed.

var cond sync.Cond
func TestFunctionA(t *testing.T){
   // ... Some codes...
   cond.Wait()
}
func TestFunctionB(t *testing.T){
   // ... Some codes...
   t.Fail()
   // ... Some codes...
   cond.Broadcast()
}

I've tried some ways, for example:

var cond sync.Cond
var A_t *testing.T
func TestFunctionA(t *testing.T){
   // ... Some codes...
   A_t = t
   // ... Some codes...
   cond.Wait()
}
func TestFunctionB(t *testing.T){
   // ... Some codes...
   t.Cleanup(func(){
      if !A_t.Failed(){
          A_t.Fail()
      }
      cond.Broadcast()
   })
   t.Fail()
   // ... Some codes...
   cond.Broadcast()
}

But the A_t.Fail() is still triggered when there is no error in FunctionB.

And I'm also considering using context.Context(). However, I have no idea how to run a Testfunction with a context.
Thank you for reading my question! I appreciate any comment or discussion!

答案1

得分: 0

一个测试不应该与另一个测试进行交互。但是,当使用__subtests__时,我们可以在测试用例之间共享任何内容。

以下是一个示例:

package main

import (
	"errors"
	"testing"
)

func TestFruits(t *testing.T) {
	var err error
	t.Run("test apple", getTestAppleFunc(&err))
	t.Run("test banana", getTestBananaFunc(&err))
}

func handleError(t *testing.T, err *error) {
	if err != nil && *err != nil {
		t.Error(*err)
	}
}

func getTestAppleFunc(err *error) func(*testing.T) {
	return func(t *testing.T) {
		handleError(t, err)
		*err = errors.New("Apple failed")
	}
}

func getTestBananaFunc(err *error) func(*testing.T) {
	return func(t *testing.T) {
		handleError(t, err)
	}
}
  • 在函数getTestBananaFuncgetTestAppleFunc中,错误的指针被作为参数传递。
  • 在上面的示例中,getTestAppleFunc首先被执行。
  • 如果在getTestAppleFunc中分配了一个错误,就像上面的示例中所示,getTestBananaFunc函数将失败。
英文:

A test should not interact with another test. But we can share anything between test cases when using subtests.

Here is an example:

package main

import (
	"errors"
	"testing"
)

func TestFruits(t *testing.T) {
	var err error
	t.Run("test apple", getTestAppleFunc(&err))
	t.Run("test banana", getTestBananaFunc(&err))
}

func handleError(t *testing.T, err *error) {
	if err != nil && *err != nil {
		t.Error(*err)
	}
}

func getTestAppleFunc(err *error) func(*testing.T) {
	return func(t *testing.T) {
		handleError(t, err)
		*err = errors.New("Apple failed")
	}
}

func getTestBananaFunc(err *error) func(*testing.T) {
	return func(t *testing.T) {
		handleError(t, err)
	}
}
  • In the functions getTestBananaFunc and getTestAppleFunc, the pointer of error is passed as an argument.
  • In the above example, getTestAppleFunc is executed first.
  • If an error is assigned in getTestAppleFunc, as shown in the above example, the getTestBananaFunc function will fail.

huangapple
  • 本文由 发表于 2023年5月22日 11:27:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/76302871.html
匿名

发表评论

匿名网友

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

确定