How to calculate total code coverage for tests - go

I need to calculate code coverage for golang project where source of tests will be integration tests written in Java language . This requires go build to be instrumented first and then run on server so that tests can run and we will get to know after tests have ended, how much is code coverage? I haven't found a single reference for this on internet all there is present is unit tests which can be run easily and used to calculate coverage

First of all generate the coverage profile by using the -coverprofile flag and tell the command where to store the information.
% go test ./... -coverprofile cover.out
? some.project/somepkg [no test files]
ok some.project/somepkg/service 0.329s coverage: 53.3% of statements
Than use go tool cover with the -func flag and point it to the previously generated file. This will show you the code coverage for every single package withing your project and down at the bottom the total coverage.
% go tool cover -func cover.out
some.project/somepkg/service/.go:27: FuncA 100.0%
some.project/somepkg/service/service.go:33: FuncB 100.0%
some.project/somepkg/service/service.go:51: FuncC 0.0%
total: (statements) 53.3%
% go tool cover -func cover.out | fgrep total:
total: (statements) 53.3%
% go tool cover -func cover.out | fgrep total | awk '{print $3}'
100.0%
% go tool cover -func cover.out | fgrep total | awk '{print substr($3, 1, length($3)-1)}'
100.0

Before go 1.20 you could not do it. Only coverage for unit tests was supported.
However with go 1.20 it is now possible
https://go.dev/testing/coverage/:
Beginning in Go 1.20, Go supports collection of coverage profiles from applications and from integration tests, larger and more complex tests for Go programs.
https://go.dev/doc/go1.20:
To collect coverage data for a program, build it with go build's -cover flag, then run the resulting binary with the environment variable GOCOVERDIR set to an output directory for coverage profiles. See the 'coverage for integration tests' landing page for more on how to get started. For details on the design and implementation, see the proposal.

Related

Go Test Coverage, over different packages [duplicate]

This question already has answers here:
No test coverage when tests are in a different package
(2 answers)
Go Coverage not including functions in other package
(2 answers)
Closed 2 years ago.
I have been writing an rest service I have the following structure
/controllers
/domain/dao
/services
after writing a lot of tests for each individual package with mocks for each stage, I thought it would be quicker to just write tests against the controller and mock the database, so in that I know the /domain/dao layer is being called.
My problem now is when I run code coverage I do not get the coverage for my /service or the /domain/dao even though I know the code is being called
Any ideas on how to get my code coverage on all files?
You can try the flag -coverpkg
go test --cover -coverpkg=./services ./... -coverprofile=cover.out
To check all the packages in the folder /services as well, you can try:
go test --cover -coverpkg=./services/... ./... -coverprofile=cover.out
Just a side note - I usually add -covermode=count
go test --cover -covermode=count -coverpkg=./services/... ./... -coverprofile=cover.out
Then, you can use go tool to see it as html:
go tool cover -html=cover.out

Go: Wrong coverage when there is no tests for a package

I have a Go project with the following structure:
foo/foo.go
foo/foo_test.go
main.go
As you notice, there is no test for main.go.
I collect the coverage report using the following command:
go test ./foo ./ -coverprofile=coverage.txt -covermode=atomic
Here ./foo and ./ show where to look for packages.
Problem: I send the coverage report to codecov.io which shows that my code is 100% covered with tests. But this is not true as my main.go has no tests at all.
It seems like the system only counts those packages that explicitly specify test files.
Question: How to fix the coverage report in the way that it will count information about untested packages?
Note: You can find my project on GitHub and the real statistic is here. The project has a different structure, but the issue persists (wrong coverage).
The -coverpkg flag may be used to specify the packages that are used as the basis of coverage analyis.
Quoting from Command go: Testing flags:
-coverpkg pattern1,pattern2,pattern3
Apply coverage analysis in each test to packages matching the patterns.
The default is for each test to analyze only the package being tested.
See 'go help packages' for a description of package patterns.
Sets -cover.
So in your specific example this will do it:
go test -coverpkg=.,./foo -coverprofile=coverage.txt -covermode=atomic . ./foo
To apply it for a complete module / project, you may use:
go test -coverpkg=./... -coverprofile=coverage.txt -covermode=atomic ./...
Another option is to place an "empty" test file into the folders of packages that do not currently have a test file. That way they will be naturally included in default coverage analysis, but obviously nothing will be covered from them.
See related discussion on github:
cmd/go: go test -cover & go test -coverprofile should always output a coverage #24570
try this one:
go test -coverpkg=./... -race -coverprofile=coverage.txt -covermode=atomic ./..

Ginkgo to cobertura and JUnit

I am using Shippable as my CI and my project is based on Go 1.11. All the unit tests are written in BDD style using Ginkgo and Gomega. In my test pipeline, I have something like:
gocov test ./... | gocov-xml > shippable/codecoverage/coverage.xml
go test -v ./... | go-junit-report > shippable/testresults/junitresults.xml
This will create the coverage file in Cobertura format and unit test report in JUnit format.
In my project, we have multiple test suites. I am planning to use Ginkgo CLI to perform coverage and unit test instead of gocov and go test. Something like:
ginkgo -r -cover -outputdir=./shippable/codecoverage/ -coverprofile=coverage.txt
ginkgo -r -focus="\[Unit\]" -outputdir=./shippable/testresults/ -coverprofile=unit.txt
Now the problem is that I am unable to convert the coverage.txt file to equivalent Cobertura format XML file (which shippable will require) and unit.txt file to equivalent JUnit XML file.
I've seen how to generate the JUnit file from a test suite but in my project, we have multiple test suite, which will result in multiple JUnit files, which I don't want.
Any idea, how can I convert and use them?
To create the Cobertura format:
Nevermind, figured out myself.
Generate the cover using covermode as set
ginkgo -r -cover -covermode=set -outputdir=shippable/codecoverage/ -coverprofile=coverage.out
Now, we need to remove duplicate entries of mode: set
awk '!seen[$0]++' shippable/codecoverage/coverage.out > shippable/codecoverage/coverage-fix.out
Finally, convert to Cobertura
bash gocov convert shippable/codecoverage/coverage-fix.out | gocov-xml > shippable/codecoverage/coverage.xml

Go Coverage Report Integration with Jenkins

I wonder if there's any tool that can convert go test -coverprofile=cover.out into the formats that Jenkins can accept? I found some tools like go-junit-report and go2xunit, but they actually just convert output from go test -v, which is not the coverage report.
I want to know the detailed test coverage in Jenkins directly. Basically, I want to see the output from go tool cover -func=cover.out and go tool cover -html=cover.out in Jenkins webpage.
There are several go tools for converting coverage data from go test to Cobertura for Jenkins: gocover-cobertura, or gocov with gocov-xml.
You can use gocover-cobertura as follows:
$ go get github.com/t-yuki/gocover-cobertura
$ go test -coverprofile=cover.out example.com/demo/...
ok example.com/demo 0.008s coverage: 0.0% of statements
ok example.com/demo/cmd/demo 0.020s coverage: 23.4% of statements
$ gocover-cobertura < cover.out > coverage.xml
$ head coverage.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE coverage SYSTEM "http://cobertura.sourceforge.net/xml/coverage-04.dtd">
<coverage line-rate="0.35415787" branch-rate="0" version="" timestamp="1520609235359" lines-covered="839" lines-valid="2369" branches-covered="0" branches-valid="0" complexity="0">
<sources>
<source>/usr/local/go/src</source>
<source>/Users/wilfred/workspace/go-scratch/src</source>
</sources>
<packages>
<package name="example.com/demo/cmd/demo" line-rate="0.4848485" branch-rate="0" complexity="0">
<classes>
Note that you'll need Go 1.10+ to run -coverprofile against multiple packages in one run.
https://github.com/AlekSi/gocov-xml
This is what we need. Use Coberuta plugin to generate the coverage profile.
There isn't a dedicated plugin for Go coverage reports, nor really for generic code coverage.
For reports like this, I use the HTML Publisher Plugin to publish .html files created during a build.

"go test" reports incorrect statement coverage

I have a package with only two Go file: one defines the main function and the other is for the tests.
Now assume that I have cd into this package and run the following command:
$ go test -cover
PASS
coverage: 41.8% of statements
ok github.com/suzaku/dummage 0.010s
As you can see, this works correctly.
But I want to generate a HTML report, so after some googling I use the following command:
$ go test -run=Coverage -coverprofile=c.out github.com/suzaku/dummage
ok github.com/suzaku/dummage 0.010s coverage: 1.8% of statements
Note that this time the coverage drops to 1.8%.
What can I do to fix this?
Are you sure you need that -run=Coverage flag in your go test? This means it will only run tests that match Coverage. If you just want to generate a cover profile for that tests, run go test -coverprofile c.out github.com/suzaku/dummage. Then you may run go tool cover -html c.out to see the HTML report.
If you added -run=Coverage on purpose, then it's expected behavior - the amount of code that runs during -run=Coverage is much less than while running all tests, and the test coverage is calculated for the entire package.

Resources