Skip to content
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

testscript: merge coverage from all test binary executions #119

Merged
merged 1 commit into from
Jan 31, 2021

Conversation

mvdan
Copy link
Collaborator

@mvdan mvdan commented Jan 18, 2021

(see commit message)

@mvdan
Copy link
Collaborator Author

mvdan commented Jan 18, 2021

Please do not review yet. I'm still iterating on this.

@mvdan mvdan force-pushed the merge-extra-coverage branch 2 times, most recently from d091f99 to f385bc7 Compare January 20, 2021 20:15
@mvdan
Copy link
Collaborator Author

mvdan commented Jan 20, 2021

Alright, this is ready for a first round of review. Note that this change lacks tests and docs, because I want to know if the overall design is sane before I polish it.

The main use case is testing tools which are executed indirectly, for example via 'go build -toolexec=mytool'. It is possible to set up
"mytool" in $PATH via the test binary thanks to TESTSCRIPT_COMMAND, but then those indirectly executed sub-processes do not count towards the final coverage profile.

It's fine if you think the above is a hack, or that testscript isn't designed for this. However, it nearly works with minimal effort, except for coverage profiles.

The basic idea with this feature is that, if the test package's TestMain exports TESTSCRIPT_COVER_EXTRA, any coverage profiles found there after all scripts have run are merged into the final profile. A working example is probably the easiest way to show how this works: mvdan/garble-fork@9306f01

Another way to design this API would be to pass some sort of parameter to testscript.RunMain. That seemed hard to do in a backwards-compatible way, though.

I did not try to design this API on a per-script basis since it makes little sense; go test -coverprofile works on all tests being run. Custom code in TestMain is perhaps a bit low-level, but reusing the test binary with testscript for direct calls to $PATH via -toolexec is already a pretty exotic use case that requires custom code. So I think it's fine for the API to be a bit rough, as long as it works :)

I also exposed a way for TestMain to tell if coverage profiles are being collected, to avoid that extra work if they are not.

@mvdan
Copy link
Collaborator Author

mvdan commented Jan 26, 2021

We discussed this offline, and came up with a new design that I'll implement over the next week or so.

@mvdan mvdan changed the title testscript: add a way to merge extra coverage profiles WIP: testscript: add a way to merge extra coverage profiles Jan 26, 2021
@mvdan mvdan changed the title WIP: testscript: add a way to merge extra coverage profiles testscript: merge coverage from all test binary executions Jan 27, 2021
@mvdan mvdan force-pushed the merge-extra-coverage branch 5 times, most recently from eebd5f2 to 9c7658d Compare January 28, 2021 11:14
Copy link
Owner

@rogpeppe rogpeppe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great - it's actually simpler than I expected and should "just work" for people.
LGTM modulo a few comments and suggestions.

testscript/cover.go Outdated Show resolved Hide resolved
testscript/exe.go Outdated Show resolved Hide resolved
testscript/exe.go Outdated Show resolved Hide resolved
testscript/exe.go Outdated Show resolved Hide resolved
testscript/exe.go Outdated Show resolved Hide resolved
testscript/testscript_test.go Show resolved Hide resolved
testscript/testscript.go Outdated Show resolved Hide resolved
gotooltest/testdata/cover.txt Outdated Show resolved Hide resolved
gotooltest/script_test.go Show resolved Hide resolved
cmd/testscript/testdata/nogo.txt Show resolved Hide resolved
@mvdan
Copy link
Collaborator Author

mvdan commented Jan 28, 2021

Thanks for your review! I've applied nearly all your suggestions, minus two - I've left those threads unresolved.

I've also added a long commit message that summarizes the whole refactor.

@mvdan mvdan force-pushed the merge-extra-coverage branch 2 times, most recently from 55b027e to f4b83c3 Compare January 30, 2021 21:17
testscript/exe.go Outdated Show resolved Hide resolved
testscript/exe.go Outdated Show resolved Hide resolved
Copy link
Owner

@rogpeppe rogpeppe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM thanks! (with a couple of trivial final suggestions)

@mvdan mvdan force-pushed the merge-extra-coverage branch 2 times, most recently from 85c8689 to 21f94f0 Compare January 31, 2021 17:58
First, consolidate how top-level commands registered via RunMain are
executed. Before, they could only be run directly, such as "foo <args>".
This worked because the command would run the test binary with a special
TESTSCRIPT_COMMAND env variable, telling the sub-process what command to
run.

The unfortunate side effect was that the commands only worked when
called directly. They wouldn't work when called indirectly, such as
"exec foo" or "go build -toolexec=foo".

To fix that inconsistency, we now set up a directory in $PATH with all
the commands as copies of the test binary. The test binary sub-process
knows what command it should execute thanks to os.Args[0]. This also
lets us get rid of the TESTSCRIPT_COMMAND dance.

Second, make all top-level command executions write coverage profiles if
the -coverprofile test flag was used. Similar to the case before, this
only used to work for direct command executions, not indirect ones. Now
they all get merged into the final coverage profile.

This is accomplished by having them all write coverage profiles under a
shared directory. Once all scripts have run, the parent process walks
that directory and merges all profiles found in it.

Third, add a test that ensures both of the refactors above work well. It
lives under gotooltest, since it runs the real "go test -coverprofile".
It checks all three ways mentioned above to run a top-level command, as
well as checking that all three count towards the total coverage.

Note that some tests needed to be amended to keep working after the
refactor. For example, some tests used a custom "echo" command as well
as the system's "exec echo". Since now both of those would execute the
testscript command, rename that command to fprintargs, which is also
clearer and less ambiguous.

Similarly, dropgofrompath had to be used in one more test, and had to be
adapted to actually do the intended thing on Windows rather than just
emptying the entire PATH variable.

Also swap Go's 1.16beta1 for 1.16rc1 in CI, since the former is now
failing due to a bug in setup-go.
@mvdan mvdan merged commit dc4b495 into rogpeppe:master Jan 31, 2021
@mvdan mvdan deleted the merge-extra-coverage branch March 12, 2021 15:49
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 this pull request may close these issues.

2 participants