ある特定のファイルのテストカバレッジが、ある特定のテストファイル(群)を実行したときに一定のカバレッジ率であることを保証したいと思うことはありますか?私はあります。
そこで、 次のような spec/coverage_helper.rb
を用意して、 spec/rails_helper.rb
などから require すると、 COVERAGE_ASSERTION=app/models/ability.rb rspec spec/models/ability_spec.rb:99
のようなコマンドをCIで実行したときに一定のテストカバレッジ以下のときにCIがコケるようにしました。
# frozen_string_literal: true class CoverageAssertion class CoverageAssertionFailure < StandardError end attr_reader :file_map attr_reader :highline def initialize require "highline" coverage_assertion = ENV['COVERAGE_ASSERTION'] @file_map = Hash[coverage_assertion.split(',').map { |pair| pair.split(':') }] @file_map.transform_keys! { |key| Pathname.new(key) } @file_map.transform_values! { |value| value.to_f } @highline = HighLine.new end def format(result) failure_message = +"" result.groups.each do |_name, files| files.each do |f| filename = Pathname.new(f.filename).relative_path_from(Rails.root) threshold = file_map[filename] if threshold && f.covered_percent < threshold failure_message << highline.color("#{filename}: expected at least #{threshold}% but got #{f.covered_percent.round(2)}%\n", :red) end end end if failure_message.present? raise CoverageAssertionFailure, "Coverage assertion failed!\n#{failure_message}" end end end if ENV['CI'] || ENV['COVERAGE'] || ENV['COVERAGE_ASSERTION'] require 'simplecov' require 'simplecov-lcov' # COVERAGE_ASSERTION="$file1:$least_coverage1,$file2:$least_coverage2,..." # See also .circleci/config.yml if ENV['COVERAGE_ASSERTION'] SimpleCov.formatter = CoverageAssertion else SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new( [ SimpleCov::Formatter::HTMLFormatter, SimpleCov::Formatter::LcovFormatter, ], ) end SimpleCov.start 'rails' do # add_filter [...] end end
Rails + rspec + simplecov という条件で動くはず。