如何忽略Go测试覆盖率中的生成文件

37

我的软件包中有一个生成的文件,顶部写着DO NOT EDIT。我正在使用go test -coverprofile=cover.out <package>运行软件包的测试。这将创建覆盖率文件并显示总体覆盖率百分比。但是,在计算覆盖范围时,它也包括生成的文件。是否有一种方法可以忽略生成的文件在覆盖范围计算中的影响?


你检查了 cover.out 吗?你应该注意到它包含了包文件名。你可以根据文件头部是否包含文本“DO NOT EDIT”来过滤这些行。 - user142162
在你过滤文件之后,你可以使用 go tool cover 重新分析覆盖率。 - user142162
我对Go还很陌生,知道它非常注重极简主义哲学,但是让我感到有些疯狂的是,你需要修改实际的覆盖率报告文件才能实现这一点。 - Tyler Nielsen
4个回答

29

您可以从覆盖概要中剥离生成的代码:

go test . -coverprofile cover.out.tmp
cat cover.out.tmp | grep -v "_generated.go" > cover.out
tool cover -func cover.out

根据使用的工具,这可以轻松地在流水线/制作中实现。


14
这可能导致报告底部的“总计”不准确。 - Corey Ogburn

15

以下是我能解决这个问题的方法。

通过排除dirs/pkgs

由于要运行测试并生成封面,您将指定go test命令应查找文件的pkgs,超出此pkg范围的文件将自动被忽略。以下是一个例子:

project
|_______/pkg/web/app 
|_______/pkg/web/mock -> It will be ignored.

# Command:   
$go test -failfast -tags=integration -coverprofile=coverage.out -covermode=count github.com/aerogear/mobile-security-service/pkg/web/apps

但并非所有情况都适用。例如,在文件被模拟接口程序占用的情况下,可能会不起作用,因为所需的服务、测试和模拟导入很可能会处于循环中,这是不允许的。

通过在名称定义中使用“_test”

如果您想要忽略在测试中使用的文件,则在名称结尾处使用_test是有意义的。例如:my_service_mock_test.go。名称以_test结尾的文件将默认被忽略。

通过从覆盖文件中删除如下内容

go test . -coverprofile cover.out.tmp
cat cover.out.tmp | grep -v "_generated.go" > cover.out
tool cover -func cover.out

附注:我找不到任何评论或标记来排除它们。


附注:使用grep -v "_generated.go" cover.out.tmp代替cat cover.out.tmp | grep -v "_generated.go" - undefined

14
大多数Go工具都是基于包进行操作的,因为一个包本身就形成了一个整体单元,可能在整体上非常有用。从包中排除文件很容易“破坏”包:被排除的文件可能包含(重要的)包初始化代码,或者甚至会导致其余的包文件无法编译。
go test也不例外:它也是基于包进行操作的。目前没有直接支持从包中排除文件的方法。
如果您的包可以在不生成该文件的情况下进行编译和测试,那么您可以选择将该文件生成到另一个包中,这样它就不会自然地包含在您的包的(覆盖率)测试中。
处理这个问题的另一种方法是仍然将其生成在同一个包/文件夹中,并在生成的文件中使用特殊的构建标签,在运行覆盖率测试时可以排除这些标签。您可以在这里阅读更多关于构建标签的内容:Build Constraints,以及这里:What is the right approach to encapsulate platform specific code in Go? 如果生成的文件需要编译/测试包,则您仍有一个选择:使用生成文件的“内部”包。内部包仅对以“内部”文件夹为根的包树可用,这意味着您可以在内部包中导出任何标识符,编译器确保它们不会被“意外”的方​​式使用。您可以在此处阅读有关内部包的更多信息:我可以在多个源目录中开发go包吗? 此外,请考虑编写或生成生成代码的测试的选项,这可能是一种好的实践,因此您不必使用技巧将其排除在覆盖测试之外。

10

你可以从测试中用grep筛选出那些目录。

所以,不是:

go test ./...
你需要这样做:

你需要这样做:

go test `go list ./... | grep -v ./excluded/autogen/directory/here`

同时,确保您不要添加尾随的/。这会导致不完美的工作。


"go list" 列出包含 Go 包的目录,而不是文件。因此,使用 "grep -v" 只能排除整个包,而不能排除文件。如果您想要排除同一包中的单个模拟文件,则这种方法行不通。如果目标是忽略整个包,则更简单的“解决方案”是不为该包编写测试。覆盖率仅考虑找到测试的包。 - mrpandey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接