【问题标题】:Does go test run unit tests concurrently?go test 是否同时运行单元测试?
【发布时间】:2022-05-24 05:29:47
【问题描述】:

运行go test 时,它会运行以_test.go 结尾的文件,方法是运行以TestXxx 格式开头的函数并使用(*t testing.T) 模块。我想知道_test.go 文件中的每个函数是否同时运行,或者它是否最终单独运行每个函数?它是否为每个人创建了一个例行程序?如果它确实为每个人创建了一个 goroutine,我可以以某种方式监控 goroutine 吗?有没有可能做类似golibrary.GoRoutines() 的事情并为每个实例获取一个实例并以某种方式或类似的方式监控它们?


注意:本题假设你使用的是 go (testing) 自带的测试框架。

【问题讨论】:

  • 你想达到什么目的?
  • 所以这就是事情......我拥有的每个 TestXXX 函数都会创建一个与某个端口号连接的进程。如果他们都尝试连接到同一个端口或做类似的奇怪事情,那就太奇怪了。我想控制它们连接的端口号,并通过一些原子增量或终止每个进程使其唯一,这样我就不需要多个不同的端口号。不过,我现在也很想知道如何监控 go-routines。

标签: unit-testing go


【解决方案1】:

tests are executed as goroutines,因此同时执行

但是,正如@jacobsa 所指出的,测试默认情况下不会并行运行。要启用并行执行,您必须在测试用例中调用 t.Parallel() 并适当设置 GOMAXPROCS 或提供 -parallel N(默认设置为 GOMAXPROCS)。

在并行运行测试时,最简单的解决方案是为端口号设置一个全局切片和一个全局原子递增索引,作为切片中的测试和端口之间的关联。这样您就可以控制端口号并为每个测试使用一个端口。示例:

import "sync/atomic"

var ports [...]uint64 = {10, 5, 55}
var portIndex uint32

func nextPort() uint32 {
    return atomic.AddUint32(&portIndex, 1)
}

【讨论】:

  • 我还可以制作一个全局锁(或通道),这会使所有 go-routines 冻结,除了应该运行的那个。这样,我就不必使用不同的端口号(如果测试数量急剧增加,这很好,我不必担心我使用什么端口号)。不过,它确实会降低并发性...
  • 顺便说一句,感谢查看 testing.go 的 src,我不会想到看那里。现在我学会了查看 go src 以找到此类问题的答案。谢谢! :)
  • 我认为您错过了只有在调用 t.Parallel 时才能同时运行测试。
  • @jacobsa 不,当你这样做时,它们会并行执行。但为了清楚起见,我会更新我的答案。
  • 请注意,go test ./... 默认并行运行 不同包 的测试,除非将 -p 1 传递给它。
【解决方案2】:

是的,正如其他答案已经指出的那样,只有在添加 t.Parallel() 并使用 -parallel 标签运行时,一个 _test.go 文件中的测试才会并行运行。

但是 - 默认情况下,命令 go test 会针对不同的包运行并行测试,默认是可用的 CPU 数量(请参阅 go help build

所以要禁用并行执行,您应该像这样运行测试 go test -p 1 ./...

【讨论】:

    【解决方案3】:

    是的,如果你添加这个: t.Parallel() 到你的函数。

    像这样:

    func TestMyFunction(t *testing.T) {
        t.Parallel()
        //your test code here
    
    }
    

    【讨论】:

      【解决方案4】:

      您可以通过使用t.Parallel 标记测试来同时运行它们 然后使用-parallel 标志运行测试。

      你可以看到other testing flags here

      【讨论】:

        【解决方案5】:

        go 中的“并行测试”有两个方面。

        1. 并行测试包(文件夹)。由-p 标志控制。

        go help build:

            -p n
                the number of programs, such as build commands or
                test binaries, that can be run in parallel.
                The default is GOMAXPROCS, normally the number of CPUs available.
        
        1. 测试包内的测试。由-parallel 标志控制,测试需要使用t.Parallel() 启用。

        go help testflag:

            -parallel n
                Allow parallel execution of test functions that call t.Parallel.
                The value of this flag is the maximum number of tests to run
                simultaneously; by default, it is set to the value of GOMAXPROCS.
                Note that -parallel only applies within a single test binary.
                The 'go test' command may run tests for different packages
                in parallel as well, according to the setting of the -p flag
                (see 'go help build').
        

        对于#1,您可以通过在多个包中进行测试来直接观察到这一点,并强制它们在睡眠状态下长时间运行。然后 ps aux 和 grep 运行,你会看到并行的单独进程。

        或使用-x 详细标志运行。这很清楚地表明了正在发生的事情。每个包启动一次测试(例如,在几个包中有 *_test.go 文件。注意我正在运行 go test -x ./... -v -count=1 |& ruby -pe 'print Time.now.strftime("[%Y-%m-%d %H:%M:%S] ")' |& tee temp.out 并使用 -p=N -parallel=M 的各种配置,您可以看到它们并行运行:

        [2022-05-09 17:22:26] $WORK/b065/understandinit.test -test.paniconexit0 -test.timeout=10m0s -test.parallel=1 -test.v=true -test.count=1
        [2022-05-09 17:22:26] $WORK/b001/main.test -test.paniconexit0 -test.timeout=10m0s -test.parallel=1 -test.v=true -test.count=1
        [2022-05-09 17:22:26] $WORK/b062/mainsub.test -test.paniconexit0 -test.timeout=10m0s -test.parallel=1 -test.v=true -test.count=1
        

        【讨论】:

          猜你喜欢
          • 2010-09-26
          • 1970-01-01
          • 2017-09-10
          • 1970-01-01
          • 2012-11-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-09-01
          相关资源
          最近更新 更多