我尝试在本文中运行sytemTest: https://www.elastic.co/blog/code-coverage-for-your-golang-system-tests
所以请遵循提示 首先,我创建一个名为main_test.go的系统测试文件,如下所示:
func TestSystem(t *testing.T) {
t.Logf("systemtest mod=%v", *SystemTest)
if *SystemTest {
t.Log("runing system test....")
main()
}
}
执行此单元测试时,将执行整个主要功能
然后我建立一个测试字典:
go test -c -covermode=count -coverpkg ./... -o main.test
并在我的测试环境中执行测试二进制文件
./main.test -systemTest -test.coverprofile ./coverage.cov
因为该程序将侦听并等待客户的请求,所以除非我退出manunal,否则它不会退出,这意味着Coverprofile将不会被生成
所以我启动了一个计时器,以在15秒后停止程序... 但是,当程序退出时,coverprofile仍然无法生成
如果测试未调用main,则可以正常生成coverprofile
查看主要功能
var mkrtExitWait sync.WaitGroup
var mkrtExitCode int
var mkrtRunning bool = false
func MKrtRun() int {
mkrtExitWait.Add(1)
mkrtRunning = true
mkrtExitWait.Wait()
return mkrtExitCode
}
func MKrtExit(code int) {
if !mkrtRunning {
os.Exit(code)
} else {
mkrtRunning = false
mkrtExitCode = code
mkrtExitWait.Done()
}
}
func main() {
// listen and serve code
......
if *SystemTest { // a command flag
go func(){
time.Sleep(time.Second * 10)
MKrtExit(0)
}()
}
MKrtRun()
}
我尝试了一些方法来生成coverage文件,如下所示,但它不起作用:
发送客户端请求以告诉测试服务器在程序运行时执行os.Exit(0)
发送客户端请求,告诉测试服务器在程序运行时执行panic()
杀死强制退出程序的过程
出什么问题了?
如何生成覆盖文件?
答案 0 :(得分:1)
为我解决的问题(并在@darkwing的答案中提到)是标志顺序。
当我首先放置-test.coverprofile=coverage.cov
时,它可以工作,并创建了coverage.cov文件。
注意:我必须在标志名称和值之间添加=
符号。
我也不需要在其他go例程中运行它。
答案 1 :(得分:0)
在测试中运行一些外部测试时通常使用系统测试
这意味着您需要修改主程序才能在某些中断时退出。 SIGINT是最适合您的主程序退出的信号,因为它可以通过POSIX信号合规性进行确认
这可以通过添加以下内容
来完成 // Handle graceful shutdown of http server via OS Interrupt
quit := make(chan os.Signal)
signal.Notify(quit, os.Interrupt)
// Block a goroutine on Interrupt channel and close
// http server to exit gracefully
go func() {
<-quit
log.Info("receive interrupt signal")
MKrtEixt(0)
}()
所以您的测试步骤应该是
答案 2 :(得分:0)
我弄清楚了为什么不能生成Coverprofile的原因..
主要协程由测试二进制文件启动,它将等待util完成所有测试任务,并最终覆盖coverage文件。 主功能测试是一项任务,因此如果主功能执行os.Exit(0),则不会生成coverage文件。 在我的测试程序中,当主要功能测试任务结束时,还有其他一些测试任务要执行,其中一个被I / O事件阻止而没有超时,因此它与主要功能测试任务无关。
答案 3 :(得分:0)
OP提示了一个答案,但并未给出答案。关键在于,要编写coverage配置文件,程序需要将执行返回到TestMain
,而不能仅调用os.Exit(0)
因此,真正需要做的只是在主goroutine中使用return
处理一点代码。下面是示例代码,它使用以下代码编译测试二进制文件后运行:
go test -c -covermode=count -cover -coverpkg ./...
然后运行如下(引号在Windows的Powershell中是必需的,但在cmd中不是必需的):
testmain.test.exe "-test.coverprofile" coverage.cov systemTest
我发现由于某种原因,仅当我的自定义标记systemTest
紧随-test.coverprofile coverage.cov
之后才生成覆盖文件。这是一个简单的示例:
main.go:
func main() {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
done := make(chan struct{})
go func() {
<-c
done <- struct{}{}
}()
go func() {
for {
// this is where your real program runs
fmt.Println("printing and sleeping")
time.Sleep(1 * time.Second)
}
}()
<-done
return
}
main_test.go:
func TestMain(t *testing.T) {
run := false
for _, arg := range os.Args {
switch {
case arg == "systemTest":
run = true
}
}
if run {
main()
fmt.Println("returned from main")
}
}
灵感:https://www.cyphar.com/blog/post/20170412-golang-integration-coverage 和https://www.elastic.co/blog/code-coverage-for-your-golang-system-tests