-
Notifications
You must be signed in to change notification settings - Fork 554
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
Implement branch coverage support for exit status modifiers #934
Implement branch coverage support for exit status modifiers #934
Conversation
0605c7b
to
d61ae99
Compare
@PragTob this is my first PR in this repo! I tried to follow the contributions guide, but please, please let me know if there's anything I missed |
lib/simplecov/configuration.rb
Outdated
end | ||
|
||
# | ||
# Refuses any coverage drop. That is, coverage is only allowed to increase. | ||
# SimpleCov will return non-zero if the coverage decreases. | ||
# | ||
def refuse_coverage_drop | ||
maximum_coverage_drop 0 | ||
def refuse_coverage_drop(criteria = [DEFAULT_COVERAGE_CRITERION]) |
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 desired default behavior? Or would desired default behavior be to refuse coverage for lines and branches?
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.
Great question!
I'd say default should be for both. It's backwards incompatible but it's the right behavior imo.
Hi @PragTob, just wanted to re-ping this PR in case it was missed :) Let me know how it looks! |
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 the great PR! 💚 🎉 🚀
As already discussed elsewhere, terribly sorry for the long time it took me to get to this. Had a rough time and spent no time on OSS minus one bug fix release. It's not the standard I hold myself to, esp. for a new contributor and such extensive work. So, sincerest apologies again.
Also, yes there are a lot of comments - but it's a great PR. I review very thoroughly and a lot of the comments are just naming discussions or ideas how to cut maybe a bit of code. Some of them also require no action at all and are just little thoughts. Also just because I comment something doesn't mean I'm right - I can be wrong so please counter argue and ask 😁
Some things that we still need to do here:
- make sure it works when a last_run file in the old format is present so people upgrading aren't greeted by an error, this would probably be best done through a cucumber scenario
- check that these work in general also as a feature test (SimpleCov breaks in unexpected ways and is a big integration nightmare hence I like good integration tests that for instance check that these actually make a build fail). We do something similar in the miniminimum coverage feature:
simplecov/features/minimum_coverage.feature
Lines 65 to 81 in aa64b87
@branch_coverage Scenario: Works together with branch coverage and the new criterion announcing both failures Given SimpleCov for Test/Unit is configured with: """ require 'simplecov' SimpleCov.start do add_filter 'test.rb' enable_coverage :branch minimum_coverage line: 90, branch: 80 end """ When I run `bundle exec rake test` Then the exit status should not be 0 And the output should contain "Line coverage (88.09%) is below the expected minimum coverage (90.00%)." And the output should contain "Branch coverage (50.00%) is below the expected minimum coverage (80.00%)." And the output should contain "SimpleCov failed with exit 2" - unit testing the refuse_coverage_drop new way of specifying the criteria + fixing it
I know lots of this is cucumber related which quite some people are not familiar with. I'm happy to help you point you the right direction. If you feel like it'd be too much I'm also happy to take it over myself.
You made a lot of great work, I let you wait so long and I comment so much - have a couple of extra bunnies:
CHANGELOG.md
Outdated
========== | ||
|
||
## Enhancements | ||
* Can now define the minimum_coverage_by_file, maximum_coverage_drop and refuse_coverage_drop by branch as well as line |
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.
"for branch as well as line coverage" might read nicer :)
# same as above (the default is to only refuse line drop) | ||
SimpleCov.refuse_coverage_drop :line | ||
# refuse drop for line and branch | ||
SimpleCov.refuse_coverage_drop :line, :branch |
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.
Thanks for updating the docs and with nice examples to boot! 👍
@@ -40,7 +40,7 @@ Feature: | |||
""" | |||
{ | |||
"result": { | |||
"covered_percent": 88.09 | |||
"line": 88.09 |
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 backwards incompatible, but I think it's fine. We should just mention it in the changelog. People might want to update their respective files to keep working after the release.
One thing though, we should write a test to make sure that we don't raise an error if an "old style" file is present. That'd be a catastrophic upgrade experience for folks if simplecov now failed all the time.
We could call it "covered_percent_branch" for branch coverage but it's not desirable long term, hence I'm fine with the incompatibility.
@@ -285,20 +285,22 @@ def merge_timeout(seconds = nil) | |||
# | |||
# Default is 0% (disabled) | |||
# | |||
|
|||
# rubocop:disable Metrics/CyclomaticComplexity |
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.
🎉
lib/simplecov/configuration.rb
Outdated
@minimum_coverage = coverage | ||
end | ||
|
||
def validate_coverage!(coverage, coverage_setting) |
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.
thanks for extracting!
Generally it's avoided to create bang/!
methods if there's no non bang alternative. You probably did it to signify that it raises, we might extend the name to communicate that raise_on_invalid_coverage
but just validate_coverage
might also be fine.
I'll leave that naming decision up to you, but would like to get rid off the !
:)
def coverage_statistics_by_file | ||
@coverage_statistics_by_file ||= | ||
(res = result.coverage_statistics_by_file).each do |criteria, stats| | ||
res[criteria] = stats.map { |stat| SimpleCov.round_coverage(stat.percent) } |
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 we need this code?
I'm probably be wrong but we're "just" rounding the percentages, couldn't we do that down in compute_minimum_violations
while we're mapping and call SimpleCov.round_coverage
on actual_percent
there? 🤔
end | ||
end | ||
|
||
def compute_minimum_violations |
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.
similar these aren't the violations yet so I'd name it something like compute_minimum_coverage_data
or something as with drop above
spec/configuration_spec.rb
Outdated
@@ -47,70 +47,70 @@ | |||
end | |||
end | |||
|
|||
describe "#minimum_coverage" do | |||
shared_examples "checks coverage settings" do |coverage_setting| |
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 feel like "setting coverage expections" or something would be a better name (we also check the results not just that what is given is correct)
spec/configuration_spec.rb
Outdated
after :each do | ||
config.clear_coverage_criteria | ||
end | ||
|
||
it "does not warn you about your usage" do | ||
expect(config).not_to receive(:warn) | ||
config.minimum_coverage(100.00) | ||
config.send(coverage_setting, 100.00) |
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.
hey can you please replace send
with public_send
basically everywhere here? :)
It's a pet peeve of mine, it helps us in only calling public methods so we won't accidentally make them private or something + highlighting we are indeed testing public methods and not private ones
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.
Thanks for the tip, I didn't know about public_send
!
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.
Thanks for the feedback @PragTob , round 1 of changes are up! It is very possible I missed one (or more!) of your comments. If so, please let me know 😄
spec/configuration_spec.rb
Outdated
after :each do | ||
config.clear_coverage_criteria | ||
end | ||
|
||
it "does not warn you about your usage" do | ||
expect(config).not_to receive(:warn) | ||
config.minimum_coverage(100.00) | ||
config.send(coverage_setting, 100.00) |
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.
Thanks for the tip, I didn't know about public_send
!
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.
lib/simplecov/configuration.rb
Outdated
def refuse_coverage_drop(*criteria) | ||
if criteria.empty? | ||
SUPPORTED_COVERAGE_CRITERIA.each do |coverage_criteria| | ||
enable_coverage(coverage_criteria) |
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 don't think we should enable all coverage if we're not given any arguments 🤔
We should probably just use all the coverage critieria that have been enabled. There should be a reader for that 🤔
@@ -4,6 +4,7 @@ module SimpleCov | |||
module ExitCodes | |||
class MaximumCoverageDropCheck | |||
def initialize(result, maximum_coverage_drop) | |||
puts "REPORTING*****" |
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.
debug statements :)
def last_coverage(criterion) | ||
last_run[:result][criterion].tap do |last_coverage_percent| | ||
if !last_coverage_percent && criterion == "line" | ||
return last_run[:result][:covered_percent] |
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 don't think this works 🤔
irb(main):001:0> true.tap do return false end
Traceback (most recent call last):
6: from /home/tobi/.asdf/installs/ruby/2.7.2/bin/irb:23:in `<main>'
5: from /home/tobi/.asdf/installs/ruby/2.7.2/bin/irb:23:in `load'
4: from /home/tobi/.asdf/installs/ruby/2.7.2/lib/ruby/gems/2.7.0/gems/irb-1.2.6/exe/irb:11:in `<top (required)>'
3: from (irb):1
2: from (irb):1:in `tap'
1: from (irb):1:in `block in irb_binding'
As in can't return from inside the block and iirc tap just returns self anyhow. I think a "normal" if without tap should do the trick.
Also made me realize CI didn't run.. grmll.
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.
@PragTob thanks for the review, up again! I'm also unsure why CI didn't run.... Maybe if I squash commits? Any suggestions there?
@jemmaissroff I have no clue :( But it's most definitely on my/our side. Or on github actions. I did research it for 30 mins last time and hoped it was just a hiccup. I'll see if I can reproduce when doing my own fork and pushing to it. Might still be different but I'll give it a shot and try to fix it because without we can't really merge. (I mean ok technically I could put this on a main line branch and see it there but this setup should work). Also super confusing since it did work on opening the PR. |
@jemmaissroff Ok I tried something I'm not sure if it'll work as my test didn't work, but that might be because it was my account. If this doesn't fix it I'll probably have to create a secondary account to test it out. You might need to rebase the PR though (or merge new main) as the changes might only apply if your base reference is the new main of the repo. |
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.
d245717
to
6722a7c
Compare
@PragTob okay, rebased off of main, and CI ran and passed 🎉 ! So should be all set to merge? Let me know if I need to squash my commits or anything else? |
@jemmaissroff looks good thank you! I think I'll give it another pass and if it's nothing major I'll just do it myself (changes + squashing) - all good. Thank you so much! |
This implements branch coverage support for
:minimum_coverage_by_file
,:maximum_coverage_drop
, and:refuse_coverage_drop
.Resolves Issue #844.