gpt4 book ai didi

go - 显示无盲点的功能测试覆盖率

转载 作者:IT王子 更新时间:2023-10-29 00:45:01 26 4
gpt4 key购买 nike

我有一个不是用 golang 编写的生产 golang 代码和功能测试。功能测试运行编译后的二进制文件。我的生产代码的非常简化的版本在这里:main.go:

package main

import (
"fmt"
"math/rand"
"os"
"time"
)

func main() {
rand.Seed(time.Now().UTC().UnixNano())
for {
i := rand.Int()
fmt.Println(i)
if i%3 == 0 {
os.Exit(0)
}
if i%2 == 0 {
os.Exit(1)
}
time.Sleep(time.Second)
}
}

我想为我的功能测试构建覆盖率配置文件。为此,我添加了包含以下内容的 main_test.go 文件:

package main

import (
"os"
"testing"
)

var exitCode int

func Test_main(t *testing.T) {
go main()
exitCode = <-exitCh
}

func TestMain(m *testing.M) {
m.Run()
// can exit because cover profile is already written
os.Exit(exitCode)
}

并修改main.go:

package main

import (
"flag"
"fmt"
"math/rand"
"os"
"runtime"
"time"
)

var exitCh chan int = make(chan int)

func main() {
rand.Seed(time.Now().UTC().UnixNano())
for {
i := rand.Int()
fmt.Println(i)
if i%3 == 0 {
exit(0)
}
if i%2 == 0 {
fmt.Println("status 1")
exit(1)
}
time.Sleep(time.Second)
}
}

func exit(code int) {
if flag.Lookup("test.coverprofile") != nil {
exitCh <- code
runtime.Goexit()
} else {
os.Exit(code)
}
}

然后我构建覆盖二进制文件:

go test -c -coverpkg=.  -o myProgram

然后我的功能测试运行这个覆盖二进制文件,如下所示:

./myProgram -test.coverprofile=/tmp/profile
6507374435908599516
PASS
coverage: 64.3% of statements in .

然后我构建了显示覆盖率的 HTML 输出:

$ go tool cover -html /tmp/profile -o /tmp/profile.html
$ open /tmp/profile.html

html coverage profile

问题

exit 方法永远不会显示 100% 的覆盖率,因为 if flag.Lookup("test.coverprofile") != nil。所以行 os.Exit(code) 是我的覆盖结果的一个盲点,尽管事实上,功能测试在这条线上进行并且这条线应该显示为绿色。

另一方面,如果我删除条件 if flag.Lookup("test.coverprofile") != nil,行 os.Exit(code) 将在不构建覆盖率配置文件的情况下终止我的二进制文件。

如何重写 exit()main_test.go 以显示覆盖无盲点

第一个想到的解决方案是time.Sleep():

func exit(code int) {
exitCh <- code
time.Sleep(time.Second) // wait some time to let coverprofile be written
os.Exit(code)
}
}

但这不是很好,因为会导致生产代码在退出前变慢。

最佳答案

根据我们在评论中的对话,我们的覆盖率配置文件永远不会包含该行代码,因为它永远不会被执行。

如果没有看到您的完整代码,就很难想出一个合适的解决方案,但是您可以做一些事情来增加覆盖率而不会牺牲太多。

func Main 和 TestMain

GOLANG 的标准做法是避免测试主应用程序入口点,因此大多数专业人员将尽可能多的功能提取到其他类中,以便轻松测试它们。

GOLANG 测试框架允许您在没有主函数的情况下测试您的应用程序,但您可以在其中使用 TestMain 函数,该函数可用于测试代码需要在主函数上运行的位置线。下面是 GOLANG Testing 的一个小例子。

It is sometimes necessary for a test program to do extra setup or teardown before or after testing. It is also sometimes necessary for a test to control which code runs on the main thread. To support these and other cases, if a test file contains a function: func TestMain(m *testing.M)

查看 GOLANG Testing 了解更多信息。

工作示例

下面是一个测试代码所有功能的示例(覆盖率为 93.3%,我们将其设为 100%)。我对您的设计做了一些更改,因为它不太适合测试,但功能仍然相同。

主要包

dofunc.go

import (
"fmt"
"math/rand"
"time"
)

var seed int64 = time.Now().UTC().UnixNano()

func doFunc() int {
rand.Seed(seed)
var code int
for {
i := rand.Int()
fmt.Println(i)
if i%3 == 0 {
code = 0
break
}
if i%2 == 0 {
fmt.Println("status 1")
code = 1
break
}
time.Sleep(time.Second)
}
return code
}

dofunc_test.go

package main

import (
"testing"
"flag"
"os"
)

var exitCode int

func TestMain(m *testing.M) {
flag.Parse()
code := m.Run()
os.Exit(code)
}

func TestDoFuncErrorCodeZero(t *testing.T) {
seed = 2

if code:= doFunc(); code != 0 {
t.Fail()
}
}

func TestDoFuncErrorCodeOne(t *testing.T) {
seed = 3

if code:= doFunc(); code != 1 {
t.Fail()
}
}

main.go

package main

import "os"

func main() {
os.Exit(doFunc());
}

运行测试

如果我们使用封面配置文件构建我们的应用程序。

$ go test -c -coverpkg=. -o example

然后运行它。

$ ./example -test.coverprofile=/tmp/profile

运行测试

1543039099823358511
2444694468985893231
6640668014774057861
6019456696934794384
status 1
PASS
coverage: 93.3% of statements in .

所以我们看到我们得到了 93% 的覆盖率,我们知道这是因为我们没有对 main 的任何测试覆盖率来解决这个问题,我们可以为它编写一些测试(这不是一个好主意) 因为代码有 os.Exit 或者我们可以重构它,所以它非常简单,功能很少,我们可以将它排除在我们的测试之外。

要从覆盖率报告中排除 main.go 文件,我们可以使用构建 tags,方法是在 main.go< 的第一行放置标签注释 文件。

//+build !test

有关构建标志的更多信息,请查看此链接:http://dave.cheney.net/2013/10/12/how-to-use-conditional-compilation-with-the-go-build-tool

这将告诉 GOLANG 该文件应该包含在存在标签 build 的构建过程中,但NOT 存在标签 test 的地方。

查看完整代码。

//+build !test

package main

import "os"

func main() {
os.Exit(doFunc());
}

我们需要构建稍微不同的覆盖应用程序。

$ go test -c -coverpkg=. -o example -tags test

运行它会是一样的。

$ ./example -test.coverprofile=/tmp/profile

我们得到下面的报告。

1543039099823358511
2444694468985893231
6640668014774057861
6019456696934794384
status 1
PASS
coverage: 100.0% of statements in .

我们现在可以构建覆盖 html。

$ go tool cover -html /tmp/profile -o /tmp/profile.html

Coverage HTML Report

关于go - 显示无盲点的功能测试覆盖率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39690509/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com