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

huangapple go评论76阅读模式
英文:

How to ignore generated files from Go test coverage

问题

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

英文:

I have a generated file in my package with DO NOT EDIT on top. I am running tests for my package with go test -coverprofile=cover.out &lt;package&gt;. This creates coverage profile and shows total coverage percentage. But it also includes generated files while calculating the coverage. Is there a way to ignore generated files in coverage calculation?

答案1

得分: 29

你可以从覆盖率文件中去除生成的代码:

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

根据使用的工具,可以在流水线/Makefile中轻松实现这一点。

英文:

You could strip the generated code from the cover profiles:

go test . -coverprofile cover.out.tmp
cat cover.out.tmp | grep -v &quot;_generated.go&quot; &gt; cover.out
tool cover -func cover.out

Depending on the used tools this can be implemented easily in the pipeline/make.

答案2

得分: 14

大多数Go工具都是针对包进行操作的,因为一个包本身就是一个可以完整使用的“单元”。从包中排除文件可能会很容易地“破坏”这个包:被排除的文件可能包含(关键的)包初始化代码,甚至可能导致剩余的包文件无法编译。

go test也不例外:它也是针对包进行操作的。目前没有直接支持从包中排除文件的功能。

如果你的包可以在不包含生成的文件的情况下进行编译和测试,你可以选择将生成的文件放在一个不同的包中,这样它就不会自然地包含在你的包的(覆盖率)测试中。

另一种处理方法是仍然将其生成在同一个包/文件夹中,并在生成的文件中使用特殊的构建标签,在运行覆盖率测试时可以排除这些标签。你可以在这里了解更多关于构建标签的信息:构建约束,以及这里:https://stackoverflow.com/questions/35428963/what-is-the-right-approach-to-encapsulate-platform-specific-code-in-go/35429081#35429081

如果生成的文件需要用于编译/测试包,那么你仍然有一个选择:为生成的文件使用一个“internal”包。内部包只对以internal文件夹为根的包树可见,这意味着你可以在内部包中导出任何标识符,编译器会确保它们不会被“意外”的使用。你可以在这里了解更多关于内部包的信息:https://stackoverflow.com/questions/45899203/can-i-develop-a-go-package-in-multiple-source-directories/45902409#45902409

此外,还可以考虑为生成的代码编写或生成测试,这可能是一个好的实践,这样你就不必使用技巧将其排除在覆盖率测试之外。

英文:

Most Go tools operate on packages, because a package itself forms a unit that may be useful in its entirety. Excluding files from a package could easily "break" the package: the excluded file may contain (crucial) package initialization code or may even cause the remaining package files fail to compile.

go test is no exception: it also operates on packages. There is no first-hand support to exclude files from a package.

If your package may be compiled and tested without the generated file, you may opt to generate the file into a different package, and then it won't be included in your package's (coverage) test naturally.

Another way to handle this would be to still generate it in the same package / folder, and use special build tags in the generated files, which you may exclude when running the coverage test. You can read more about build tags here: Build Constraints, and here: https://stackoverflow.com/questions/35428963/what-is-the-right-approach-to-encapsulate-platform-specific-code-in-go/35429081#35429081

If the generated file is needed to compile / test the package, then you still have an option: use an internal package for the generated file. Internal packages are only available to the package tree rooted at the internal folder, which means you may export any identifiers in an internal package, the compiler ensures they won't be used by "unintended" parties. You can read more about internal packages here: https://stackoverflow.com/questions/45899203/can-i-develop-a-go-package-in-multiple-source-directories/45902409#45902409

Also consider the option to write or generate test for the generated code, which may be good practice anyway, so you wouldn't have to use tricks to exclude them from coverage tests.

答案3

得分: 14

以下是我翻译好的内容:

根据我解决这个需求的方式。

通过排除目录/包

由于要运行测试并生成覆盖率报告,您需要指定go test命令应该在哪些包中查找文件,超出这些包的文件将自动被忽略。以下是一个示例:

project
|_______/pkg/web/app 
|_______/pkg/web/mock -> 它将被忽略。

# 命令:   
$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

附注:我找不到可以排除它们的注释或标签。

英文:

Following the ways that I could solve this need.

By excluding dirs/pkgs

Since to run the test and generated the cover you will specify the pkgs where the go test command should look for the files out of this pkg will be ignored automatically. Following an example

project
|_______/pkg/web/app 
|_______/pkg/web/mock -&gt; It will be ignored.

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

However, it cannot be applied in all cases. For example, in the case of the files be mock routines of your interfaces it may not work very well because the imports which are required into the service, test and mock probably will be in a cycle and in this not allowed.

By using "_test" in the name definitions

If you would like to ignore files which are used in the tests then make sense use _test at the end of the name. For example, my_service_mock_test.go. The files with _test at the end of the name will be ignored by default.

By removing from the cover file as follows

go test . -coverprofile cover.out.tmp
cat cover.out.tmp | grep -v &quot;_generated.go&quot; &gt; cover.out
tool cover -func cover.out

PS.: I could not find a comment or tag which would exclude them.

答案4

得分: 10

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

所以,不要使用:

go test ./...

而是使用:

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

另外,请确保不要添加尾部的斜杠“/”,这样不会完全起作用。

英文:

You can grep those directories out from the test.

So, instead of:

go test ./...

You do this:

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

Also, make sure that you don't add a trailing /. It doesn't work perfectly.

huangapple
  • 本文由 发表于 2018年4月27日 23:14:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/50065448.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定