猿问

在golang中使用子流程测试时如何生成单元测试覆盖率?

我对我们的大部分代码进行了单元测试。但是我无法弄清楚如何为 main 包中的 main() 中的某些代码生成单元测试覆盖率。

主要功能非常简单。它基本上是一个选择块。它读取标志,然后调用另一个函数/执行某事,或者只是在屏幕上打印帮助。但是,如果命令行选项设置不正确,它将以各种错误代码退出。因此,需要进行子过程测试。

我尝试了子流程测试技术,但修改了代码,使其包含覆盖标志:

cmd := exec.Command(os.Args[0], "-test.run=TestMain -test.coverprofile=/vagrant/ucover/coverage2.out")

这是原始代码:https : //talks.golang.org/2014/testing.slide#23上面幻灯片的解释:http : //youtu.be/ndmB0bj7eyw?t=47m16s

但它不会生成封面配置文件。我一直无法弄清楚为什么不。它确实为执行测试的主进程生成覆盖配置文件,但是在子进程中执行的任何代码当然不会被标记为已执行。

我尝试实现尽可能多的代码覆盖率。我不确定我是否遗漏了什么,或者是否有更简单的方法来做到这一点。或者,如果这是不可能的。


30秒到达战场
浏览 210回答 3
3回答

汪汪一只猫

我会考虑需要测试的逻辑main():func main() {    start(os.Args)}func start(args []string) {    // old main() logic}通过这种方式,您可以在start()不改变os.Args.

烙印99

我采用了另一种不涉及重构 main() 的方法:请参阅此提交:我使用全局(未导出)变量:var args []string然后在main(),os.Args除非var args设置了私有,否则我使用:a := os.Args[1:]if args != nil {    a = args}flag.CommandLine.Parse(a)在我的测试中,我可以设置我想要的参数:args = []string{"-v", "-audit", "_tests/p1/conf/gitolite.conf"}main()而且我仍然实现了 100% 的代码覆盖率,甚至超过了main().

万千封印

在 Go 1.11 中使用 @VonC 解决方案,我发现我必须在每次重新定义标志的测试中重置 flag.CommandLine,以避免“重新定义标志”恐慌。:    for _, check := range checks {        t.Run("flagging " + check.arg, func(t *testing.T) {            flag.CommandLine = flag.NewFlagSet(cmd, flag.ContinueOnError)            args = []string{check.arg}            main()        })    }
随时随地看视频慕课网APP

相关分类

Go
我要回答