2017-08-16 99 views
0

我正在开展项目,我的任务是为一个软件包编写一些测试。测试需要访问不同包中的全局变量。这个全局变量可能是在不同软件包的测试中设置/访问的。因为默认情况下,测试会针对不同的包并行运行。因此,设置/访问此变量可能会创建竞争条件。什么是最好的方式来同步不同包中涉及全局变量的测试?

最简单的同步方法是创建一个跨越不同包的共享sync.Mutex。话虽如此,我试图把这个sync.Mutex放在声明全局变量的xxx.go的xxx_test.go中,不幸的是,由于范围的限制,另一个软件包无法访问这个Mutex。最终,我发现我必须将这个sync.Mutex添加到专门用于测试的实用程序包中,然后不同的程序包可以访问此Mutex以实现该全局变量的同步目的。

我是新郎朗。我只是觉得我需要创建一个实用程序包来实现测试中的同步目的很尴尬,另一方面,如果另一个开发人员在另一个包中做了一些测试,他/她可能不知道在哪里可以找到这个sync.Mutex。有没有更好的方法来实现这个同步的目的与一个优雅的解决方案。

非常感谢!

+2

这是原因之一,为什么不推荐使用全局变量...: ) – cd1

+0

确实,谢谢。 –

回答

2

这个问题不可能广泛。 Entire books已被写入主题。

但是,由于您具体询问全局变量,最简单的答案是:不要使用全局变量。

我们总是被教导全局变量是一种反模式。测试是全局变量和单例是反模式的主要原因之一。

如果可能,请将您的全局状态重构为,至少允许为实例变量,而不是全局。然后,您可以将该实例传递给您的函数进行测试。

作为一个简单的例子,假设你有以下的全局变量,以及使用它的功能:

var globalFoo = 123 

func doFoo() string { 
    return fmt.Sprintf("foo = %d", globalFoo) 
} 

修改你的函数把你的变量作为自变量:

func doFoo(foo int) string { 
    return fmt.Sprintf("foo = %d", foo) 
} 

这如果你的全局状态是一个数据库连接或大量的变量,可能会更复杂,但原理是一样的:不要使用全局变量;而不是传递变量。

在传统的代码库,一个方法,以允许测试,而无需改变你的函数的签名,是创建简单的环绕功能:

func doFoo() string { 
    return realDoFoo(globalFoo) 
} 

func realDoFoo(foo int) string { 
    fmt.Sprintf("foo = %s", foo) 
} 
+0

感谢您的回答,这是非常有益的! –

相关问题