Skip to content
Actionable code coverage.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.
specs support test_ which some minitest projects use May 9, 2019
.gitignore implement Apr 17, 2016
Gemfile.lock v1.3.2 May 9, 2019
MIT-LICENSE initial by Apr 16, 2016
Rakefile silence warnings Dec 5, 2016 coverage image May 19, 2019
single_cov.gemspec mark required ruby version Dec 10, 2016

Single Cov Build Status coverage

Actionable code coverage.

rspec spec/foobar_spec.rb
114 example, 0 failures

lib/foobar.rb new uncovered lines introduced (2 current vs 0 configured)",
Uncovered lines:
  • Missing coverage on every 💚 test run
  • Catch coverage issues before making PRs
  • Easily add coverage enforcement for legacy apps
  • 2-5% runtime overhead on small files, compared to 20% for SimpleCov
  • Branch coverage on ruby 2.5+ (disable via branches: false)
  • Use with forking_test_runner for per test coverage
# Gemfile
gem 'single_cov', group: :test

# spec/spec_helper.rb ... load before loading rails / minitest / libraries
require 'single_cov'
SingleCov.setup :rspec

# spec/foobar_spec.rb ... add covered! call to test files
require 'spec_helper'

describe "xyz" do ...


Call setup before loading minitest.

SingleCov.setup :minitest
require 'minitest/autorun'

Unfound target file

# change all guessed paths
SingleCov.rewrite { |f| f.sub('lib/unit/', 'app/models/') }

# mark directory as being in app and not lib
SingleCov::APP_FOLDERS << 'presenters'

# add 1-off
SingleCov.covered! file: 'scripts/weird_thing.rb'

Known uncovered

Add the inline comment # uncovered to not be alerted about it being uncovered.

Prevent addition of new uncovered code, without having to cover all existing code.

Alternatively mark how many lines are uncovered:

SingleCov.covered! uncovered: 4

Verify all code has tests & coverage

# spec/coverage_spec.rb
SingleCov.not_covered! # not testing any code in lib/

describe "Coverage" do
  it "does not allow new untested code" do
    # option :tests to pass custom Dir.glob results

  it "does not allow new untested files" do
    # option :tests and :files to pass custom Dir.glob results
    # :untested to get it passing with known untested files

Automatic bootstrap

Run this from irb to get SingleCov added to all test files.

tests = Dir['spec/**/*_spec.rb']
command = "bundle exec rspec %{file}"

tests.each do |f|
  content =
  next if content.include?('SingleCov.')

  # add initial SingleCov call
  content = content.split(/\n/, -1)
  insert = content.index { |l| l !~ /require/ && l !~ /^#/ }
  content[insert...insert] = ["", "SingleCov.covered!"]
  File.write(f, content.join("\n"))

  # run the test to check coverage
  result = `#{command.sub('%{file}', f)} 2>&1`
  if $?.success?
    puts "#{f} is good!"

  if uncovered = result[/\((\d+) current/, 1]
    # configure uncovered
    puts "Uncovered for #{f} is #{uncovered}"
    content[insert+1] = "SingleCov.covered! uncovered: #{uncovered}"
    File.write(f, content.join("\n"))
    # mark bad tests for manual cleanup
    content[insert+1] = "# SingleCov.covered! # TODO: manually fix this"
    File.write(f, content.join("\n"))
    puts "Manually fix: #{f} ... output is:\n#{result}"


Michael Grosser
License: MIT

You can’t perform that action at this time.