DEV Community

Cover image for Excluding files from code coverage in GO
Talal Yousif
Talal Yousif

Posted on

Excluding files from code coverage in GO

It's not uncommon to find yourself in a situation where you would like to make an exception for some code from being included in code coverage; perhaps it's auto-generated code or perhaps it's a wrapper of a third party API. Unfortunately, unlike many other languages, there is no built-in way to do this in Go (Hopefully not for too long). In this article, we go over a simple workaround to achieve this goal.

First things first, a quick recap. Code coverage can be generated using the go cover tool. From the docs, usage of the tool is described as:

Usage of 'go tool cover':
Given a coverage profile produced by 'go test':
go test -coverprofile=c.out
Open a web browser displaying annotated source code:
go tool cover -html=c.out

As such, we first run our tests using:

go test ./... -coverprofile=coverage.out
Enter fullscreen mode Exit fullscreen mode

Subsequently, we generate code coverage using:

go tool cover -html=coverage.out
Enter fullscreen mode Exit fullscreen mode

I like to run the commands one after the other in one call, like so:

go test ./... -coverprofile=coverage.out && go tool cover -html=coverage.out
Enter fullscreen mode Exit fullscreen mode

The workaround

It's simple. Code coverage is generated based on the coverprofile which is no more than a plain text file annotating which lines of each code file are covered and which are not. Remove all lines about a file from the coverprofile and it won't be included in the code coverage report. As simple as that.

Here is what a coverprofile looks like

Screenshot of a coverprofile

It wouldn't be ideal if we have to manually manipulate the coverprofile every time we want to generate code coverage. A better way would be to automate this process. For that, We need to do 2 things. The first is a file that holds paths to files to be excluded from code coverage. File paths in this file should include the full package name. I created a file named "exclude-from-code-coverage.txt". Here is a snippet of what it looks like

Screenshot of exclude-from-code-coverage.txt

The second is a script that removes files in exclude-from-code-coverage.txt from the coverprofile. This simple script (named exclude-from-code-coverage.sh) does just that:

#!/bin/sh
while read p || [ -n "$p" ] 
do  
sed -i '' "/${p//\//\\/}/d" ./coverage.out 
done < ./exclude-from-code-coverage.txt
Enter fullscreen mode Exit fullscreen mode

And finally, tying it all together:

go test ./... -coverprofile=coverage.out && ./exclude-from-code-coverage.sh && go tool cover -html=coverage.out
Enter fullscreen mode Exit fullscreen mode

Let's break it down:

  1. The first command, go test ./... -coverprofile=coverage.out runs the tests and generates the coverprofile.
  2. The second command, ./exclude-from-code-coverage.sh, removes files we want to exclude from code coverage from the coverprofile.
  3. The third command, go tool cover -html=coverage.out, generated the code coverage report.

Top comments (5)

Collapse
 
talalyousif profile image
Talal Yousif

One last thing to note, that I find interesting, is that one way to exclude a file from coverage natively would be to not have tests on the whole package. What I mean by this is: if you have a package called api and you have 3 files under this package, api_one.go, api_two.go and api_three.go. If you have no test files, then package api will not be counted towards the overall code coverage nor will it be considered to have 0% coverage. However, if you add a test file api_one_test.go, then your package will be included in the overall coverage percentage and it will have a coverage percentage value.

Collapse
 
marcello_h profile image
Marcelloh

go test -count=1 -coverprofile coverage.out -coverpkg=./... ./...
cat coverage.out | grep -v "mock" | grep -v "othername" > coverage.final.out

Collapse
 
mwitteveen profile image
mwitteveen • Edited

this:

test:
    CGO_ENABLED=0 go test -count=1 -coverpkg=./... -covermode=atomic -coverprofile coverage.out  ./...

    grep -v -E -f .covignore coverage.out > coverage.filtered.out
    mv coverage.filtered.out coverage.out


    CGO_ENABLED=0 go tool cover -func coverage.out
Enter fullscreen mode Exit fullscreen mode

then you can create a .covignore file and place wildcards in there
e.g.
.test.

Collapse
 
edrandall profile image
Ed Randall • Edited

We want a 1-liner, and so it seems simpler, instead of running for ./... then filtering down with a separate script, to exclude /test and /test/mock directories like this:

go test -coverprofile=coverage.out `go list ./... | egrep -v '(/test|/test/mock)$')`
Enter fullscreen mode Exit fullscreen mode

For ease-of-use we have a Makefile (who remembers all these commands anyway?) so the developer can type make coverage. These targets take care of it:

# Basic code coverage with text output
coverage:
    go test -covermode=count -coverprofile=coverage.out $(shell go list ./... | egrep -v '(/test|/test/mock)$$')
    go tool cover -func=coverage.out

# Open HTML coverage report in browser - with detailed line coverage
coverage-html: coverage
    go tool cover -html=coverage.out
Enter fullscreen mode Exit fullscreen mode
Collapse
 
pritamlipu1 profile image
pritamlipu1 • Edited

go test ./store/... ./server/... -race -v -coverprofile="coverage.out"
where store and server are 2 packages.
Note: "..." is to add subfolders as well.