-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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
proposal: testing: add magic //go:cover ignore comment #53271
Comments
same as #34639 |
See also #12504 |
Based on prior comments, Rob Pike is opposed to magic comments to control the cover tool. That makes sense, but if there's no knob for controlling the cover tool, it would be good if the tool had some way of detecting and ignoring panic("unreachable") lines on its own. Maybe |
The discoverability of that feature for new users sounds really low. I think, a builtin (or somewhere in the std): func unreachable() {
panic("unreachable")
} And the magic comment being This is a feature other modern languages integrates, for example see in rust |
See #30582 for an unreachable in the standard library. |
I understand, that Rob Pike has a strong voice, but what is about the community? As mentioned in #31280 (comment), a substantial part of the community already adopted tools, that work with magic comments to handle false positives. The If such a magic comment is introduced, nobody is required to use it and the Go team can forbid to use it in the Go standard library, the Go tooling, etc. if they really wish to do this. |
If we're never going to use them in the Go standard library and tooling, then it doesn't seem too hard to me to wrap the Go coverage tool with a wrapper that looks for the comments itself. If we add direct support in the Go coverage tool, we will be regularly rejecting patches to add them to the Go standard library. |
I'm not sure why this has to be part of cover. If you have something that reports the uncovered lines, couldn't it filter them out instead? In general we're thinking about redoing the way cover works to be more inside the compiler, and I'd rather not have the compiler need to introduce per-basic-block magic comments as a concept. |
I wrote this tool a while back: https://pkg.go.dev/rsc.io/tmp/uncover. |
This seems to be a different proposal. What I propose is functionally equivalement to |
This proposal has been added to the active column of the proposals project |
Why is it important for the coverage tool to "understand it"? |
I think the conversation is becoming a bit circular. The point isn't the percentage. It's to communicate to other devs/one's future self that a certain line can be ignored when looking at coverage summaries. Otherwise one ends up opening files that don't need to be opened just to see what the 1% uncovered lines are and then immediately closing it again after deciding that yes, the panic is unreachable. It's a waste of time. |
If that's the case, then what if cover "grays out" panic("unreachable")? |
In my experience, "coverage ignore" comments are used by developers as a hammer to pass coverage gates in CI (usually not 100%), excluding things they don't know how to test or otherwise don't understand why is only partially covered, or just fudging things when they're 0.5% below the gate.
That this is even possible makes this, imo, the wrong approach. After all, it's easy to just mark things uncovered and don't write test cases for them. As someone responsible for developer tooling, ignore comments reduce my trust in the system accurately reflecting reality. I'm sure I'm not the only one having seen services crash with "unreachable" panics, these untested code paths should continue to be reported as such. |
I'm leaving this issue open, because there are still other users who support it, but I think my preference at this point would be something like #30582 being automatically marked as ignored by coverage. If something screws up and the line does get run, it will trigger a panic, so there's no need for a "purple" accidentally covered code color. |
I'd like to understand the exact semantics of this proposed directive a bit better. Most existing Go compiler directives (ex: go:noinline, go:noescape, etc) apply to the thing that immediately follows the directive. Is this also the case for the proposed directive? Or do we need some sort of control flow analysis to figure out the set of statements to which it applies? For example, in this code, does the directive only apply to the statement on line 11, or also to the statement on line 9 as well? I would assume this to be the case, given that our code coverage setup doesn't take into account panic paths.
What about the function below-- if control flow reaches "return 42", this implies that the "if" statement has executed. Do we apply the "no cover" property to the "if" statement? That would be consistent with the previous example (again, assuming that we're not taking into account panic paths). What about the println in the defer statement?
Where can I place go:nocover directives? Is either of these directives illegal?
If there are multiple directives, should this be taken into account during control flow analysis? In the function below, both arms of the "if" statement have a //go:nocover directive. This implies that the "if" statement should also not be covered-- should the launchThePaperAirplane() call be also considered nocover?
|
@thanm I executed your examples with some "prior art" ( example1
example2
example3a (at the end of the file in the screenshot)The The example3bThe The example 4
Screenshot of the HTML cover reportThe HTML cover report by Summary
|
@thanm The following is my personal point of view to the examples you have provided. In general, when I think about coverage, I think in terms of branches (or code block) and I didn't care to much about potential panic paths until now (maybe, this discussion will change this, we will see). example1Because I think in terms of code blocks, I expect the example2Form my point of view, this is a rather fabricated example. The request for example3For the first The second example4Here again, my personal opinion is, that |
If this is the case in a development team, then this is a cultural issue, which can not be solved with a tool. If the option for "coverage ignore` comments does not exist, such developers find other ways to cheat the system.
The thing is, the panic will happen regardless of the fact if the code is pushed to production with the "real" coverage reported in CI or with an "adjusted" coverage. Where I work, we can see the coverage in our review process and the important part is the discussion, why some code is not covered and what can be done about it. After this discussion, in my opinion it is fine to let the tooling know (with a magic comment), that not covering a certain section is ok. Just today I had a case, with an error path, that is so unlikely, that I am happy to accept the risk of not having a test for this case. The respective code processed a JWT token. After the signature has been validated, the claims are extracted from the token, which is basically JSON unmarshal. When I got a JWT with a valid signature, chances are very small, that it contains an invalid JSON body for the claims. I don't say it is impossible to happen nor do I say, that it is not possible to create a test for this case, but from a business point of view it is just not worth the effort to write such a test in contrast to the risk. |
Based on the discussion above, this proposal seems like a likely decline. |
Maybe I should save my energy for other topics, because it seams, that this ship has likely sailed. I just want to reply to one more point. @rsc wrote some comments back:
One reason, why this needs to be part of cover (and the go tool) is editor integration. While it is possible to post process the coverage files e.g. on the command line or in CI, this is normally not an option in the editor. |
No change in consensus, so declined. |
Problem
The Go coverage tool is very useful, but there's no way to mark a line as not needing coverage. It is common to add
panic("unreachable")
in place where one expects code never to run unless there is a programmatic error. These lines show up in code coverage output as untested and must be manually inspected in order to be noted that they can be ignored and don't need to be tested.Proposal
If a line is prefaced by
//go:cover ignore
the following expression or block will be marked as "ignored".In the HTML output of the cover tool, ignored lines should be marked with yellow. If an ignored line is covered during a test, it should be reported as "ignored but covered" and marked in purple for investigation of whether a programmatic error has taken place.
Cf #31280
The text was updated successfully, but these errors were encountered: