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

Adds coverage calculation by individual file feature. #392

Merged
merged 1 commit into from
May 26, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,14 @@ You can define the minimum coverage percentage expected. SimpleCov will return n
SimpleCov.minimum_coverage 90
```

### Minimum coverage by file

You can define the minimum coverage by file percentage expected. SimpleCov will return non-zero if unmet. This is useful to help ensure coverage is relatively consistent, rather than being skewed by particularly good or bad areas of the code.

```ruby
SimpleCov.minimum_coverage_by_file 80
```

### Maximum coverage drop

You can define the maximum coverage drop percentage at once. SimpleCov will return non-zero if exceeded.
Expand Down
11 changes: 11 additions & 0 deletions lib/simplecov/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,17 @@ def maximum_coverage_drop(coverage_drop = nil)
@maximum_coverage_drop ||= (coverage_drop || 100).to_f.round(2)
end

#
# Defines the minimum coverage per file required for the testsuite to pass.
# SimpleCov will return non-zero if the current coverage of the least covered file
# is below this threshold.
#
# Default is 0% (disabled)
#
def minimum_coverage_by_file(coverage = nil)
@minimum_coverage_by_file ||= (coverage || 0).to_f.round(2)
end

#
# Refuses any coverage drop. That is, coverage is only allowed to increase.
# SimpleCov will return non-zero if the coverage decreases.
Expand Down
4 changes: 4 additions & 0 deletions lib/simplecov/defaults.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,15 @@

if SimpleCov.result? # Result has been computed
covered_percent = SimpleCov.result.covered_percent.round(2)
covered_percentages = SimpleCov.result.covered_percentages.map { |p| p.round(2) }

if @exit_status == SimpleCov::ExitCodes::SUCCESS # No other errors
if covered_percent < SimpleCov.minimum_coverage # rubocop:disable Metrics/BlockNesting
$stderr.printf("Coverage (%.2f%%) is below the expected minimum coverage (%.2f%%).\n", covered_percent, SimpleCov.minimum_coverage)
@exit_status = SimpleCov::ExitCodes::MINIMUM_COVERAGE
elsif covered_percentages.any? { |p| p < SimpleCov.minimum_coverage_by_file } # rubocop:disable Metrics/BlockNesting
$stderr.printf("File (%.2f%%) is only (%.2f%%) covered. This is below the expected minimum coverage per file of (%.2f%%).\n", least_covered_file, covered_percentages.min, SimpleCov.minimum_coverage_by_file)
@exit_status = SimpleCov::ExitCodes::MINIMUM_COVERAGE
elsif (last_run = SimpleCov::LastRun.read) # rubocop:disable Metrics/BlockNesting
diff = last_run["result"]["covered_percent"] - covered_percent
if diff > SimpleCov.maximum_coverage_drop # rubocop:disable Metrics/BlockNesting
Expand Down
11 changes: 11 additions & 0 deletions lib/simplecov/file_list.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@ def skipped_lines
map { |f| f.skipped_lines.count }.inject(&:+)
end

# Computes the coverage based upon lines covered and lines missed for each file
# Returns an array with all coverage percentages
def covered_percentages
map(&:covered_percent)
end

# Finds the least covered file and returns that file's name
def least_covered_file
sort_by(&:covered_percent).first.filename
end

# Returns the overall amount of relevant lines of code across all files in this list
def lines_of_code
covered_lines + missed_lines
Expand Down
2 changes: 1 addition & 1 deletion lib/simplecov/result.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class Result
# Explicitly set the command name that was used for this coverage result. Defaults to SimpleCov.command_name
attr_writer :command_name

def_delegators :files, :covered_percent, :covered_strength, :covered_lines, :missed_lines
def_delegators :files, :covered_percent, :covered_percentages, :least_covered_file, :covered_strength, :covered_lines, :missed_lines
def_delegator :files, :lines_of_code, :total_lines

# Initialize a new SimpleCov::Result from given Coverage.result (a Hash of filenames each containing an array of
Expand Down
8 changes: 8 additions & 0 deletions spec/file_list_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@
expect(subject.covered_percent).to eq(78.57142857142857)
end

it "has the correct covered percentages" do
expect(subject.covered_percentages).to eq([50.0, 80.0, 100.0])
end

it "has the correct least covered file" do
expect(subject.least_covered_file).to match(/sample_controller.rb/)
end

it "has the correct covered strength" do
expect(subject.covered_strength).to eq(0.9285714285714286)
end
Expand Down
18 changes: 17 additions & 1 deletion spec/result_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,15 @@
expect(subject.covered_percent).to eq(86.66666666666667)
end

[:covered_percent, :covered_strength, :covered_lines, :missed_lines, :total_lines].each do |msg|
it "has accurate covered percentages" do
expect(subject.covered_percentages).to eq([80.0, 80.0, 100.0])
end

it "has accurate least covered file" do
expect(subject.least_covered_file).to match(/sample_controller.rb/)
end

[:covered_percent, :covered_percentages, :least_covered_file, :covered_strength, :covered_lines, :missed_lines, :total_lines].each do |msg|
it "responds to #{msg}" do
expect(subject).to respond_to(msg)
end
Expand All @@ -74,6 +82,10 @@
expect(dumped_result.covered_percent).to eq(subject.covered_percent)
end

it "has the same covered_percentages" do
expect(dumped_result.covered_percentages).to eq(subject.covered_percentages)
end

it "has the same timestamp" do
expect(dumped_result.created_at.to_i).to eq(subject.created_at.to_i)
end
Expand Down Expand Up @@ -101,6 +113,10 @@
it "has 80 covered percent" do
expect(SimpleCov::Result.new(original_result).covered_percent).to eq(80)
end

it "has [80.0, 80.0] covered percentages" do
expect(SimpleCov::Result.new(original_result).covered_percentages).to eq([80.0, 80.0])
end
end

context "with groups set up for all files" do
Expand Down