Skip to content

go test -coverprofile fails under Go 1.20 #199

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
prymitive opened this issue Feb 5, 2023 · 9 comments · Fixed by #201
Closed

go test -coverprofile fails under Go 1.20 #199

prymitive opened this issue Feb 5, 2023 · 9 comments · Fixed by #201

Comments

@prymitive
Copy link

I've upgraded go to 1.20 and suddenly I'm getting this error from testscript:

cannot merge cover profiles: cannot merge coverage profile from ...: no lines found in profile: <nil>

Seems like it might be related to coverage changes documented here: https://go.dev/testing/coverage/

Removing -coverprofile-... flag allows my tests to pass.

@mvdan
Copy link
Collaborator

mvdan commented Feb 8, 2023

You're absolutely right, and I've been noticing these failures with Go tip for some weeks now.

I wrote our code to collect and merge coverage profiles years ago, before upstream planned on doing the same, but properly :) So our code is not just obsolete, but also apparently broken now. I need to delete it, and check that the new go test -cover works for testscript just like our hacky stuff did.

mvdan added a commit to mvdan/go-internal that referenced this issue Feb 8, 2023
Our code was a fairly hacky version of what Go 1.20 does for us,
since we had to externally reach into the testing internals
to do the right thing before and after each program execution.

With Go 1.20, all we actually need to do is ensure that the GOCOVERDIR
environment variable is forwarded properly. With that, test binaries
will know how to produce multiple coverage profiles, and "go test" will
know how to collect and merge them.

We could keep our hacky workaround for the sake of "deep" coverage
information for Go 1.19, but that doesn't seem worthwhile.
The old mechanism caused test flakes like rogpeppe#130,
is incompatible with Go 1.20, and is overall worse than what Go 1.20 can do.
If a user wants code coverage with the latest testscript version, they
can use Go 1.20. If they are stuck on Go 1.19 and need code coverage,
I imagine they can also stick to a slightly older testscript version.

On a main package, the old testscript with Go 1.19 reports:

	PASS
	coverage: 8.0% of statements
	total coverage: 90.1% of statements
	ok	mvdan.cc/sh/v3/cmd/shfmt	0.063s

The new testscript with Go 1.20 reports:

	PASS
		mvdan.cc/sh/v3/cmd/shfmt	coverage: 90.1% of statements
	ok	mvdan.cc/sh/v3/cmd/shfmt	0.047s

Fixes rogpeppe#130, as the RemoveAll call is no longer present.
Fixes rogpeppe#161, as the API is now deprecated.
Fixes rogpeppe#199, as "go test -coverprofile" now works on Go 1.20.
mvdan added a commit to mvdan/go-internal that referenced this issue Feb 8, 2023
Our code was a fairly hacky version of what Go 1.20 does for us,
since we had to externally reach into the testing internals
to do the right thing before and after each program execution.

With Go 1.20, all we actually need to do is ensure that the GOCOVERDIR
environment variable is forwarded properly. With that, test binaries
will know how to produce multiple coverage profiles, and "go test" will
know how to collect and merge them.

We could keep our hacky workaround for the sake of "deep" coverage
information for Go 1.19, but that doesn't seem worthwhile.
The old mechanism caused test flakes like rogpeppe#130,
is incompatible with Go 1.20, and is overall worse than what Go 1.20 can do.
If a user wants code coverage with the latest testscript version, they
can use Go 1.20. If they are stuck on Go 1.19 and need code coverage,
I imagine they can also stick to a slightly older testscript version.

On a main package, the old testscript with Go 1.19 reports:

	PASS
	coverage: 8.0% of statements
	total coverage: 90.1% of statements
	ok	mvdan.cc/sh/v3/cmd/shfmt	0.063s

The new testscript with Go 1.20 reports:

	PASS
		mvdan.cc/sh/v3/cmd/shfmt	coverage: 90.1% of statements
	ok	mvdan.cc/sh/v3/cmd/shfmt	0.047s

Fixes rogpeppe#130, as the RemoveAll call is no longer present.
Fixes rogpeppe#161, as the API is now deprecated.
Fixes rogpeppe#199, as "go test -coverprofile" now works on Go 1.20.
mvdan added a commit to mvdan/go-internal that referenced this issue Feb 9, 2023
Our code was a fairly hacky version of what Go 1.20 does for us,
since we had to externally reach into the testing internals
to do the right thing before and after each program execution.

With Go 1.20, all we actually need to do is ensure that the GOCOVERDIR
environment variable is forwarded properly. With that, test binaries
will know how to produce multiple coverage profiles, and "go test" will
know how to collect and merge them.

We could keep our hacky workaround for the sake of "deep" coverage
information for Go 1.19, but that doesn't seem worthwhile.
The old mechanism caused test flakes like rogpeppe#130,
is incompatible with Go 1.20, and is overall worse than what Go 1.20 can do.
If a user wants code coverage with the latest testscript version, they
can use Go 1.20. If they are stuck on Go 1.19 and need code coverage,
I imagine they can also stick to a slightly older testscript version.

On a main package, the old testscript with Go 1.19 reports:

	PASS
	coverage: 8.0% of statements
	total coverage: 90.1% of statements
	ok	mvdan.cc/sh/v3/cmd/shfmt	0.063s

The new testscript with Go 1.20 reports:

	PASS
		mvdan.cc/sh/v3/cmd/shfmt	coverage: 90.1% of statements
	ok	mvdan.cc/sh/v3/cmd/shfmt	0.047s

Fixes rogpeppe#130, as the RemoveAll call is no longer present.
Fixes rogpeppe#161, as the API is now deprecated.
Fixes rogpeppe#199, as "go test -coverprofile" now works on Go 1.20.
@mvdan mvdan closed this as completed in #201 Feb 9, 2023
@mvdan mvdan closed this as completed in f0583b8 Feb 9, 2023
@mvdan mvdan pinned this issue Mar 9, 2023
sentriz added a commit to sentriz/cliphist that referenced this issue Mar 26, 2023
@mvdan
Copy link
Collaborator

mvdan commented Mar 27, 2023

@mvdan mvdan unpinned this issue Mar 27, 2023
@nbgraham
Copy link

I was also getting this error. Updating to latest (v1.12.0) fixed the error, but I'm not getting the total coverage.

In this walkthrough, it shows that running go test -coverprofile=cover.out
will output something like

PASS
coverage: 0.0% of statements
total coverage: 100.0% of statements

But mine shows

PASS
coverage: 100.0% of statements

with no total coverage line. The cover.out file is created, but only with coverage on main.go, not the other files in other packages that actually contain the functionality of the CLI tool.

Everything else works. I have multiple test passing and changing the expected values fails the tests as expected. It seems that everything is being run correctly.

Do I need to enable something to get the total coverage?

I'm using Go 1.21.

@nbgraham
Copy link

I found the same in the example repo
I updated to Go 1.20 and https://github.com/rogpeppe/go-internal/releases/tag/v1.10.0 and did not see the total coverage: 100.0% of statements line

I set up a test repo. I can't get deep coverage, only one package down, it seems.
https://github.com/nbgraham/go-calculator-cli

@mvdan
Copy link
Collaborator

mvdan commented Dec 21, 2023

Ignore the old output saying "total coverage"; the new output simply outputs that percentage directly.

@nbgraham
Copy link

Ok, I can see that in my test repo.

But the cover.out file still does not include the line coverage information for the other packages. I need the cover profile for all the packages to publish to my coverage reporter (SonarQube).

@nbgraham
Copy link

But using my custom bash script it outputs the coverage profile correctly

mode: set
calculator/calculator.go:11.17,12.26 1 1
calculator/calculator.go:12.26,15.3 2 1
calculator/calculator.go:17.2,20.16 3 1
calculator/calculator.go:20.16,23.3 2 1
calculator/calculator.go:25.2,26.16 2 1
calculator/calculator.go:26.16,29.3 2 1
calculator/calculator.go:31.2,31.19 1 1
calculator/calculator.go:32.13,33.41 1 1
calculator/calculator.go:34.18,35.55 1 1
calculator/calculator.go:36.10,38.11 2 1
calculator/calculator.go:41.2,41.10 1 1
calculator/cmd/calculator/main.go:9.13,12.2 2 1
calculator/internal/add/add.go:3.24,5.2 1 1
calculator/internal/multiply/multiply.go:3.29,5.2 1 1

@mvdan
Copy link
Collaborator

mvdan commented Dec 21, 2023

But the cover.out file still does not include the line coverage information for the other packages. I need the cover profile for all the packages to publish to my coverage reporter (SonarQube).

See -coverpkg in go help testflag. I regularly use -coverpkg=./.... I don't think any of this is related to testscript, as the coverage is now done entirely by go test.

@nbgraham
Copy link

-coverpkg=./... worked! Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants