【问题标题】:What is the best way to synchronize tests in different packages which involve with a global variable?在涉及全局变量的不同包中同步测试的最佳方法是什么?
【发布时间】:2017-08-16 10:25:34
【问题描述】:

我正在做一个 go 项目,我的任务是为一个包编写一些测试。测试需要访问不同包中的全局变量。这个全局变量可能在不同包的测试中设置/访问。因为默认情况下,go testing 会针对不同的包并行运行。因此,设置/访问此变量可能会产生竞争条件。

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

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

非常感谢!

【问题讨论】:

  • 这就是不推荐使用全局变量的原因之一... :)

标签: testing go synchronization mutex parallel-testing


【解决方案1】:

这个问题太宽泛了。 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)
}

【讨论】:

    猜你喜欢
    • 2019-02-02
    • 2010-10-12
    • 2015-09-15
    • 2011-12-01
    • 2022-01-01
    • 1970-01-01
    • 2016-09-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多