37

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 <package>. 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?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Rohanil
  • 1,717
  • 5
  • 22
  • 47
  • Did you examine cover.out? You should notice that it contains the package filenames. You could filter those lines based on if the file contains the text "DO NOT EDIT" in its head. –  Apr 27 '18 at 18:16
  • After you filter the file, you can use `go tool cover` to reanalyse the coverage amount. –  Apr 27 '18 at 18:17
  • I'm still new to Go - and know there is a lot of philosophy around how minimalistic it is - but it's sort of insane to me that you need to modify the actual coverage report file to achieve this. – Tyler Nielsen Sep 26 '22 at 15:37

4 Answers4

29

You could strip the generated code from the cover profiles:

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

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

Christian
  • 3,551
  • 1
  • 28
  • 24
14

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: What is the right approach to encapsulate platform specific code in Go?

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: Can I develop a go package in multiple source directories?

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.

icza
  • 389,944
  • 63
  • 907
  • 827
14

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 -> 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 "_generated.go" > cover.out
tool cover -func cover.out

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

Camila Macedo
  • 857
  • 7
  • 10
10

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.

030
  • 10,842
  • 12
  • 78
  • 123
Jaspreet Singh
  • 409
  • 4
  • 7
  • `go list` lists directories containing a go package, not files. So doing `grep -v` can only exclude entire packages, not files. This won't work if you want to exclude a single mock file in the same package. If the goal is to ignore the entire package, then a much simpler "solution" is to not write tests for that package. Coverage only considers the packages where a test is found. – mrpandey May 05 '23 at 09:52