douzhao1912 2017-08-16 10:25
浏览 25

在涉及全局变量的不同程序包中同步测试的最佳方法是什么?

I'm working on a go project, my task is writing some tests for a package. The tests need to access a global variable in a different package. This global variable might be setup/access in different packages' testing. Because by default go testing runs in parallel for different packages. Therefore, setup/access to this variable might create race conditions.

The easiest way to synchronize is to create a shared sync.Mutex which spans in the different packages. Having said that, I tried to put this sync.Mutex in the xxx_test.go of xxx.go in which the global variable is declared, unfortunately, another package was not able to access this Mutex due to scope limitation. Eventually, I figured out I have to put this sync.Mutex to a utility package which is dedicated to testing, then different packages can access this Mutex to achieve sync purpose for that global variable.

I'm new to go lang. I just felt it's awkward that I need to create a utility package to just achieve sync purpose in the testing, on the other hand, if another developer does some testing in another package, he/she probably doesn't know where to find this sync.Mutex. Is there any better way to achieve this sync purpose with an elegant solution.

Many thanks!

  • 写回答

1条回答 默认 最新

  • doudao3170 2017-08-16 12:09
    关注

    This question is impossibly broad. Entire books have been written on the topic.

    But since you asked specifically about global variables, the simplest answer is: Don't use global variables.

    We're always taught that global variables are an anti-pattern. Testing is one of the main reasons that global variables and singletons is an anti-pattern.

    If possible, refactor your global state to at least allow an instance variable, rather than a global. Then you can pass that instance into your functions for testing.

    As a simplified example, suppose you have the following global variable, and a function which uses it:

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

    Modify your function to take your variable as an argument:

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

    This can be more complicated if your global state is a database connection, or a large number of variables, but the principle is the same: Don't use globals; pass variables instead.

    In a legacy codebase, one method to allow testing, without changing your function signatures, is to create simple wrapping functions:

    func doFoo() string {
        return realDoFoo(globalFoo)
    }
    
    func realDoFoo(foo int) string {
        fmt.Sprintf("foo = %s", foo)
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作