-
Notifications
You must be signed in to change notification settings - Fork 277
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
Add preliminary support for code coverage #692
Conversation
This looks like it's just flat out failing with the older version of Bazel. Hopefully the 0.22.0 build passes. |
@softprops you did some work on this in the past, right? Do you have any time to weigh in on the PR? |
I should add that I chose to implement this slightly different compared to the Java rules: |
@andyscott can you give a quick overview of the approach? I did a quick scan, but I haven't been following the bazel coverage support. Can you help reviewers by providing some links for us to read on how that is supposed to work? I'm very excited about this! |
As far as I can tell, there's no public documentation on how code coverage works internally in Bazel. This implementation was based off of information I gleaned from:
It's currently EOD for me. I can circle back next week and hopefully provide more info. |
@iirina you are the Bazel coverage go-to person, right? Any chance you can
give us your 2c about why you chose your direction and what you think about
using a provider?
I think (not sure) that google are very cautious about adding a provider
due to the memory footprint this adds
…On Sat, 16 Feb 2019 at 4:33 Andy Scott ***@***.***> wrote:
As far as I can tell, there's no public documentation on how code coverage
works in Bazel. This implementation was based off of information I gleaned
from:
- JacocoCoverageRunner, which wraps the test runner and handles
emitting lcov files:
https://github.com/bazelbuild/bazel/blob/0.22.0/src/java_tools/junitrunner/java/com/google/testing/coverage/JacocoCoverageRunner.java
- The java launcher template:
https://github.com/bazelbuild/bazel/blob/0.22.0/src/main/java/com/google/devtools/build/lib/bazel/rules/java/java_stub_template.txt
- Kotlin + Jacoco in Bazel:
https://github.com/bazelbuild/rules_kotlin/pull/52/files
- Lots of git grepping through the Bazel repo :).
It's currently EOD for me. I can circle back next week and hopefully
provide more info.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#692 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABUIF9RYODBFPYuilUPvAINeulP93Ab7ks5vN23cgaJpZM4a-uiz>
.
|
I skimmed the code and I’m somewhat worried about the cost of the aspect. @dslomov is there a way to achieve something similar to the aspect declaration on the attribute from command line? I tried using the regular syntax but it’s not the same |
One idea (which I’m fairly certain is possible) is to add a flag to the scala tool chain and only do work in the aspect if the flag is on. This limits the memory part and probably most of the analysis perf cost (not sure how much an aspect with a lookup and empty array return costs) |
It's pretty easy to remove the aspect and just conditionally emit an instrumented jar as the primary artifact. |
Here is a recent PR on coverage in the haskell rules: tweag/rules_haskell#699 |
Neither the usage of aspects not providers in this PR should add much to the memory footprint (it is O(size of build graph) and should not be much) |
c9f5f2f
to
bab69b3
Compare
Update: This PR works for us internally at Stripe. There also seems to be an issue with the reproducibility tests for the changes, which I'll look into. Once that's taken care of, what steps do I need to take to get this to a mergeable state? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is very exciting and one of the biggest feature additions in quite some time. Very nice work.
That said, I'd like to suggest two core changes:
- split the PR into three PRs:
- a formatting only PR that improves the formatting, but has no other changes. I assume you used some tool to format it. Can we do that on master?
- can we add this tools/bazel wrapper and a separate motivation for it.
- just the changes relating to code coverage with a minimum amount of formatting change.
- I request that you go ahead as part 3. include documentation in the README as to how generate code coverage reports, a brief explanation that there should be no additional cost to running tests in normal mode, and also give some indication of how much longer you should expect the tests to take with coverage enabled.
Thanks for taking this on.
PR: @ittaiz I think you will want to take a good look at this. I assume you all may be interested in providing code coverage reports. I love to use them to make sure I am hitting all the branches in my code in tests, without which I get nervous I have bugs lurking.
"exports", | ||
] | ||
|
||
def _combine(*entriess, base = {}): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why entriess
? Any meaning there?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's just because it's a 2d array of entry items (or a 1d array of entries). In the comprehension I have:
[
entry[_CoverageReplacements].replacements
for entries in entriess
for entry in entries
if _CoverageReplacements in entry
]
Sure thing.
`tools/bazel` was an accidental commit. I use it to easily
pin to various bazel versions, and I think it got picked up in
one of the recent commits.
I'll submit a formatting PR and then a new code coverage PR. If you want
the version pinning script, I can open a PR for that too (and configure CI
to use it).
|
This should be good to go-- it passes on 0.22.0. A fair amount of this functionality just won't work on older Bazel releases. |
All tests are passing now with the exception of the reproducibility tests, due to JMH. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this looks good. @ittaiz do you have any concerns?
We have run this on our CI, and it worked fine for us.
} | ||
|
||
@Override | ||
public void processRequest(List < String > args) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
weird spacing on the List<String>
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can fix it. Not sure how it wound up this way (perhaps my editor's Java formatter got carried away?).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any chance we can add a flag for this in the toolchain?
I have a bad feeling on the overhead of these loops in the aspect and I'd love a way to turn it off if I'm right. Should be simple to add. WDYT?
) | ||
|
||
filegroup( | ||
name = "instrumenter_files", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this indirection needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it's just a relic from the original work to develop this code. I can remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should you remove it?
|
||
rjars = out.transitive_rjars | ||
|
||
coverage_runfiles = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be needed for junior test as well, right? Is there commonality? Can/should ewe reuse?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean by junior test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Junit (damn autocorrect)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do I need to implement them for junit to have coverage?
can you merge master? I was trying to get this green by rerunning the flakey test. hasn't happened yet. |
@andyscott my understanding is that this does not change runtime of build, is that accurate? I'm in favor of merge. @ittaiz do you have any objections? |
It doesn't change the runtime. For what it's worth, I'm part of the way through feature flagging the dictionary merge loops. I should have that commit ready soon. |
Eager to see this one merged. Thanks everyone! |
This looks great. Good work. I'd like to merge. I'll give @ittaiz 12 more hours to speak up if he or Wix have any concerns. Thanks for making it configurable (although I do have concerns we have underdocumented how to use all our different options here, and that is hurting adoption). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for this work and especially for adding the configurability! I appreciate it.
Do y'all have some metrics on how this impacted (if any) your build performance? (analysis time, execution time, etc).
Also I replied to two small existing comments you didn't resolve but since I've been blocking this for a while we can merge as is and either ignore them or do a followup for them.
Your decision.
) | ||
|
||
filegroup( | ||
name = "instrumenter_files", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should you remove it?
|
||
rjars = out.transitive_rjars | ||
|
||
coverage_runfiles = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do I need to implement them for junit to have coverage?
Thanks @ittaiz I’ll let @andyscott follow up tomorrow but merge so we can iterate. Also Andy, it would be nice to make sure the README has good docs on how to use this. And also a blog post would be nice to consider Andy. |
+💯 (although I would really appreciate the clarification if junit tests
indeed need more work like I think)
…On Tue, 26 Mar 2019 at 7:07 P. Oscar Boykin ***@***.***> wrote:
Thanks @ittaiz <https://github.com/ittaiz> I’ll let @andyscott
<https://github.com/andyscott> follow up tomorrow but merge so we can
iterate.
Also Andy, it would be nice to make sure the README has good docs on how
to use this. And also a blog post would be nice to consider Andy.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#692 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABUIFxkoA-oxgsQvPlV5tQdfhOntC5l3ks5vaasSgaJpZM4a-uiz>
.
|
Just saw these comments. I'll follow up this work week! |
Is there any useful README documentation for getting started with rules_scala and code coverage or is the best place to discover that to look for coverage interfaces in the upstream bazel docs? |
This adds preliminary support for code coverage with Jacoco.
This will likely require some iteration before it's extremely robust. Ideally some of that iteration can happen in follow up work in separate PRs, since the code in this PR should mostly suffice for Scala centric projects.
I haven't tested this on any production codebases yet.