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

Add method coverage support #110

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
3 changes: 1 addition & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@ jobs:

matrix:
ruby-version:
- '2.5'
- '2.6'
- '2.7'
- '3.0'
- '3.1'
- ruby-head
- jruby
- jruby-9.3
- jruby-head

steps:
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,5 @@ coverage
rdoc
pkg
.sass-cache

.ruby-version
156 changes: 153 additions & 3 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ AllCops:
Bundler/DuplicatedGem:
Enabled: false

Gemspec/RequiredRubyVersion:
Enabled: false

Layout/AccessModifierIndentation:
EnforcedStyle: outdent

Expand Down Expand Up @@ -74,3 +71,156 @@ Style/TrailingCommaInHashLiteral:

Style/TrailingCommaInArrayLiteral:
EnforcedStyleForMultiline: "comma"

Gemspec/DateAssignment: # new in 1.10
Enabled: true

Layout/LineEndStringConcatenationIndentation: # new in 1.18
Enabled: true

Layout/SpaceBeforeBrackets: # new in 1.7
Enabled: true

Lint/AmbiguousAssignment: # new in 1.7
Enabled: true

Lint/AmbiguousOperatorPrecedence: # new in 1.21
Enabled: true

Lint/AmbiguousRange: # new in 1.19
Enabled: true

Lint/DeprecatedConstants: # new in 1.8
Enabled: true

Lint/DuplicateBranch: # new in 1.3
Enabled: true

Lint/DuplicateRegexpCharacterClassElement: # new in 1.1
Enabled: true

Lint/EmptyBlock: # new in 1.1
Enabled: true

Lint/EmptyClass: # new in 1.3
Enabled: true

Lint/EmptyInPattern: # new in 1.16
Enabled: true

Lint/IncompatibleIoSelectWithFiberScheduler: # new in 1.21
Enabled: true

Lint/LambdaWithoutLiteralBlock: # new in 1.8
Enabled: true

Lint/NoReturnInBeginEndBlocks: # new in 1.2
Enabled: true

Lint/NumberedParameterAssignment: # new in 1.9
Enabled: true

Lint/OrAssignmentToConstant: # new in 1.9
Enabled: true

Lint/RedundantDirGlobSort: # new in 1.8
Enabled: true

Lint/RequireRelativeSelfPath: # new in 1.22
Enabled: true

Lint/SymbolConversion: # new in 1.9
Enabled: true

Lint/ToEnumArguments: # new in 1.1
Enabled: true

Lint/TripleQuotes: # new in 1.9
Enabled: true

Lint/UnexpectedBlockArity: # new in 1.5
Enabled: true

Lint/UnmodifiedReduceAccumulator: # new in 1.1
Enabled: true

Lint/UselessRuby2Keywords: # new in 1.23
Enabled: true

Naming/BlockForwarding: # new in 1.24
Enabled: true

Security/IoMethods: # new in 1.22
Enabled: true

Style/ArgumentsForwarding: # new in 1.1
Enabled: true

Style/CollectionCompact: # new in 1.2
Enabled: true

Style/DocumentDynamicEvalDefinition: # new in 1.1
Enabled: true

Style/EndlessMethod: # new in 1.8
Enabled: true

Style/FileRead: # new in 1.24
Enabled: true

Style/FileWrite: # new in 1.24
Enabled: true

Style/HashConversion: # new in 1.10
Enabled: true

Style/HashExcept: # new in 1.7
Enabled: true

Style/IfWithBooleanLiteralBranches: # new in 1.9
Enabled: true

Style/InPatternThen: # new in 1.16
Enabled: true

Style/MapToHash: # new in 1.24
Enabled: true

Style/MultilineInPatternThen: # new in 1.16
Enabled: true

Style/NegatedIfElseCondition: # new in 1.2
Enabled: true

Style/NestedFileDirname: # new in 1.26
Enabled: true

Style/NilLambda: # new in 1.3
Enabled: true

Style/NumberedParameters: # new in 1.22
Enabled: true

Style/NumberedParametersLimit: # new in 1.22
Enabled: true

Style/OpenStructUse: # new in 1.23
Enabled: true

Style/QuotedSymbols: # new in 1.16
Enabled: true

Style/RedundantArgument: # new in 1.4
Enabled: true

Style/RedundantSelfAssignmentBranch: # new in 1.19
Enabled: true

Style/SelectByRegexp: # new in 1.22
Enabled: true

Style/StringChars: # new in 1.12
Enabled: true

Style/SwapValues: # new in 1.1
Enabled: true
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,4 @@ DEPENDENCIES
yui-compressor

BUNDLED WITH
2.3.10
2.4.3
2 changes: 1 addition & 1 deletion assets/stylesheets/application.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
//= require ./reset.css
//= require_directory ./plugins/
//= require ./screen.css
//= require ./screen.css
5 changes: 5 additions & 0 deletions assets/stylesheets/screen.css
Original file line number Diff line number Diff line change
Expand Up @@ -314,3 +314,8 @@ thead th {
.source_table .missed-branch:nth-child(even) {
background-color: #cc6e6e;
}

.t-missed-method-summary ul {
margin: 0;
padding-left: 2em;
}
39 changes: 32 additions & 7 deletions lib/simplecov-html.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@
major, minor, patch = SimpleCov::VERSION.scan(/\d+/).first(3).map(&:to_i)
if major < 0 || minor < 9 || patch < 0
raise "The version of SimpleCov you are using is too old. "\
"Please update with `gem install simplecov` or `bundle update simplecov`"
"Please update with `gem install simplecov` or `bundle update simplecov`"
end

module SimpleCov
module Formatter
class HTMLFormatter
class HTMLFormatter # rubocop:disable Metrics/ClassLength
def initialize
@branchable_result = SimpleCov.branch_coverage?
@branch_coverage = SimpleCov.branch_coverage?
@method_coverage = SimpleCov.method_coverage?
end

def format(result)
Expand All @@ -32,18 +33,31 @@ def format(result)
end

def output_message(result)
"Coverage report generated for #{result.command_name} to #{output_path}. #{result.covered_lines} / #{result.total_lines} LOC (#{result.covered_percent.round(2)}%) covered."
parts = []
parts << "Coverage report generated for #{result.command_name} to #{output_path}"
parts << "Line coverage: #{render_stats(result, :line)}"
parts << "Branch coverage: #{render_stats(result, :branch)}" if branch_coverage?
parts << "Method coverage: #{render_stats(result, :method)}" if method_coverage?

parts.join("\n")
end

def branchable_result?
def branch_coverage?
# cached in initialize because we truly look it up a whole bunch of times
# and it's easier to cache here then in SimpleCov because there we might
# still enable/disable branch coverage criterion
@branchable_result
@branch_coverage
end

def method_coverage?
# cached in initialize because we truly look it up a whole bunch of times
# and it's easier to cache here then in SimpleCov because there we might
# still enable/disable branch coverage criterion
@method_coverage
end

def line_status?(source_file, line)
if branchable_result? && source_file.line_with_missed_branch?(line.number)
if branch_coverage? && source_file.line_with_missed_branch?(line.number)
"missed-branch"
else
line.status
Expand Down Expand Up @@ -126,6 +140,17 @@ def shortened_filename(source_file)
def link_to_source_file(source_file)
%(<a href="##{id source_file}" class="src_link" title="#{shortened_filename source_file}">#{shortened_filename source_file}</a>)
end

def render_stats(result, criterion)
stats = result.coverage_statistics.fetch(criterion)

Kernel.format(
"%<covered>d / %<total>d (%<percent>.2f%%)",
covered: stats.covered,
total: stats.total,
percent: stats.percent
)
end
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion public/application.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion simplecov-html.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Gem::Specification.new do |gem|
gem.summary = gem.description
gem.license = "MIT"

gem.required_ruby_version = ">= 2.4"
gem.required_ruby_version = ">= 2.6"

gem.files = `git ls-files`.split("\n")
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
Expand Down
27 changes: 24 additions & 3 deletions views/file_list.erb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
(<%= covered_percent(source_files.covered_percent) %>)
</div>

<% if branchable_result? %>
<% if branch_coverage? %>
<div class="t-branch-summary">
<span><b><%= source_files.total_branches %></b> total branches, </span>
<span class="green"><b><%= source_files.covered_branches %></b> branches covered</span> and
Expand All @@ -35,6 +35,15 @@
</div>
<% end %>

<% if method_coverage? %>
<div class="t-method-summary">
<span><b><%= source_files.total_methods %></b> total methods, </span>
<span class="green"><b><%= source_files.covered_methods %></b> methods covered</span> and
<span class="red"><b><%= source_files.missed_methods %></b> methods missed.</span>
(<%= covered_percent(source_files.method_covered_percent) %>)
</div>
<% end %>

<div class="file_list--responsive">
<table class="file_list">
<thead>
Expand All @@ -46,12 +55,18 @@
<th class="cell--number">Lines covered</th>
<th class="cell--number">Lines missed</th>
<th class="cell--number">Avg. Hits / Line</th>
<% if branchable_result? %>
<% if branch_coverage? %>
<th class="cell--number">Branch Coverage</th>
<th class="cell--number">Branches</th>
<th class="cell--number">Covered branches</th>
<th class="cell--number">Missed branches </th>
<% end %>
<% if method_coverage? %>
<th class="cell--number">Method Coverage</th>
<th class="cell--number">Methods</th>
<th class="cell--number">Covered methods</th>
<th class="cell--number">Missed methods </th>
<% end %>
</tr>
</thead>
<tbody>
Expand All @@ -64,12 +79,18 @@
<td class="cell--number"><%= source_file.covered_lines.count %></td>
<td class="cell--number"><%= source_file.missed_lines.count %></td>
<td class="cell--number"><%= sprintf("%.2f", source_file.covered_strength.round(2)) %></td>
<% if branchable_result? %>
<% if branch_coverage? %>
<td class="<%= coverage_css_class(source_file.branches_coverage_percent) %> strong cell--number t-file__branch-coverage"><%= sprintf("%.2f", source_file.branches_coverage_percent.round(2)) %> %</td>
<td class="cell--number"><%= source_file.total_branches.count %></td>
<td class="cell--number"><%= source_file.covered_branches.count %></td>
<td class="cell--number"><%= source_file.missed_branches.count %></td>
<% end %>
<% if method_coverage? %>
<td class="<%= coverage_css_class(source_file.methods_coverage_percent) %> strong cell--number t-file__method-coverage"><%= sprintf("%.2f", source_file.methods_coverage_percent.round(2)) %> %</td>
<td class="cell--number"><%= source_file.total_methods.count %></td>
<td class="cell--number"><%= source_file.covered_methods.count %></td>
<td class="cell--number"><%= source_file.missed_methods.count %></td>
<% end %>
</tr>
<% end %>
</tbody>
Expand Down
2 changes: 1 addition & 1 deletion views/layout.erb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<link rel="icon" type="image/png" href="<%= assets_path('favicon.png') %>" />
</head>

<body<%= ' data-branch-coverage=true' if branchable_result? %>>
<body<%= ' data-branch-coverage=true' if branch_coverage? %>>
<div id="loading">
<img src="<%= assets_path('loading.gif') %>" alt="loading"/>
</div>
Expand Down