Skip to content

Commit

Permalink
Make code/test coverage a thing we care about
Browse files Browse the repository at this point in the history
It's not perfect, but it is something.

Full line coverage, full branch coverage, checked for every PR.
  • Loading branch information
Burgestrand committed Oct 10, 2024
1 parent 3a32194 commit 5451990
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 1 deletion.
26 changes: 26 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,38 @@ jobs:
run: bundle exec rspec
env:
COVERAGE: 1
- name: Upload coverage results
uses: actions/upload-artifact@v4
with:
include-hidden-files: true
name: coverage-results
path: coverage
retention-days: 1
- name: Upload code coverage to Code Climate
run: |
./cc-test-reporter after-build \
--coverage-input-type simplecov \
./coverage/.resultset.json
coverage-check:
permissions:
checks: write
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Download coverage results
uses: actions/download-artifact@v4
with:
name: coverage-results
path: coverage
- uses: joshmfrankel/simplecov-check-action@be89e11889202cc59efb14aab2a7091622fa9aad
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
minimum_suite_coverage: 100
minimum_file_coverage: 100
coverage_json_path: coverage/simplecov-check-action.json

rubocop:
runs-on: ubuntu-latest
steps:
Expand Down
3 changes: 3 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ Layout/CaseIndentation:
Layout/FirstHashElementIndentation:
EnforcedStyle: consistent

Layout/FirstArrayElementIndentation:
EnforcedStyle: consistent

Layout/EndAlignment:
EnforcedStyleAlignWith: variable

Expand Down
17 changes: 16 additions & 1 deletion lib/pundit/rspec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,29 @@ def description(user, record)
failure_message(&failure_message_proc)
failure_message_when_negated(&failure_message_when_negated_proc)
else
# :nocov:
# Compatibility with RSpec < 3.0, released 2014-06-01.
match_for_should(&match_proc)
match_for_should_not(&match_when_negated_proc)
failure_message_for_should(&failure_message_proc)
failure_message_for_should_not(&failure_message_when_negated_proc)
# :nocov:
end

if ::RSpec.respond_to?(:current_example)
def current_example
::RSpec.current_example
end
else
# :nocov:
# Compatibility with RSpec < 3.0, released 2014-06-01.
def current_example
example
end
# :nocov:
end

def permissions
current_example = ::RSpec.respond_to?(:current_example) ? ::RSpec.current_example : example
current_example.metadata.fetch(:permissions) do
raise KeyError, <<~ERROR.strip
No permissions in example metadata, did you forget to wrap with `permissions :show?, ...`?
Expand Down
78 changes: 78 additions & 0 deletions spec/simple_cov_check_action_formatter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# frozen_string_literal: true

require "simplecov"
require "json"

class SimpleCovCheckActionFormatter
SourceFile = Data.define(:source_file) do
def covered_strength = source_file.covered_strength

def to_json(*)
{
filename: source_file.filename,
covered_percent: source_file.covered_percent,
coverage: source_file.coverage_data,
covered_strength: covered_strength.nan? ? 0.0 : covered_strength,
covered_lines: source_file.covered_lines.count,
lines_of_code: source_file.lines_of_code
}.to_json
end
end

Result = Data.define(:result) do
def included?(source_file) = result.filenames.include?(source_file.filename)

def files
result.files.filter_map do |source_file|
next unless result.filenames.include? source_file.filename

SourceFile.new(source_file)
end
end

def to_json(*) # rubocop:disable Metrics/AbcSize
{
timestamp: result.created_at.to_i,
command_name: result.command_name,
files: files,
metrics: {
covered_percent: result.covered_percent,
covered_strength: result.covered_strength.nan? ? 0.0 : result.covered_strength,
covered_lines: result.covered_lines,
total_lines: result.total_lines
}
}.to_json
end
end

FormatterWithOptions = Data.define(:formatter) do
def new = formatter
end

class << self
def with_options(...)
FormatterWithOptions.new(new(...))
end
end

def initialize(output_filename: "coverage.json", output_directory: SimpleCov.coverage_path)
@output_filename = output_filename
@output_directory = output_directory
end

attr_reader :output_filename, :output_directory

def output_filepath = File.join(output_directory, output_filename)

def format(result_data)
result = Result.new(result_data)
json = result.to_json
File.write(output_filepath, json)
puts output_message(result_data)
json
end

def output_message(result)
"Coverage report generated for #{result.command_name} to #{output_filepath}. #{result.covered_lines} / #{result.total_lines} LOC (#{result.covered_percent.round(2)}%) covered." # rubocop:disable Layout/LineLength
end
end
11 changes: 11 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,19 @@

if ENV["COVERAGE"]
require "simplecov"
require "simplecov_json_formatter"
require_relative "simple_cov_check_action_formatter"
SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new([
SimpleCov::Formatter::HTMLFormatter,
SimpleCov::Formatter::JSONFormatter,
SimpleCovCheckActionFormatter.with_options(
output_filename: "simplecov-check-action.json"
)
])
SimpleCov.start do
add_filter "/spec/"
enable_coverage :branch
primary_coverage :branch
end
end

Expand Down

0 comments on commit 5451990

Please sign in to comment.