lib/simplecov.rb in simplecov-0.18.0.beta1 vs lib/simplecov.rb in simplecov-0.18.0.beta2
- old
+ new
@@ -44,20 +44,55 @@
#
# Please check out the RDoc for SimpleCov::Configuration to find about available config options
#
def start(profile = nil, &block)
require "coverage"
- load_profile(profile) if profile
- configure(&block) if block_given?
+ initial_setup(profile, &block)
@result = nil
- self.running = true
self.pid = Process.pid
- start_coverage_measurment
+ start_coverage_measurement
end
#
+ # Collate a series of SimpleCov result files into a single SimpleCov output.
+ # You can optionally specify configuration with a block:
+ # SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"]
+ # OR
+ # SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"], 'rails' # using rails profile
+ # OR
+ # SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"] do
+ # add_filter 'test'
+ # end
+ # OR
+ # SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"], 'rails' do
+ # add_filter 'test'
+ # end
+ #
+ # Please check out the RDoc for SimpleCov::Configuration to find about
+ # available config options, or checkout the README for more in-depth
+ # information about coverage collation
+ #
+ def collate(result_filenames, profile = nil, &block)
+ raise "There's no reports to be merged" if result_filenames.empty?
+
+ initial_setup(profile, &block)
+
+ results = result_filenames.flat_map do |filename|
+ # Re-create each included instance of SimpleCov::Result from the stored run data.
+ (JSON.parse(File.read(filename)) || {}).map do |command_name, coverage|
+ SimpleCov::Result.from_hash(command_name => coverage)
+ end
+ end
+
+ # Use the ResultMerger to produce a single, merged result, ready to use.
+ @result = SimpleCov::ResultMerger.merge_and_store(*results)
+
+ run_exit_tasks!
+ end
+
+ #
# Returns the result for the current coverage run, merging it across test suites
# from cache using SimpleCov::ResultMerger if use_merging is activated (default)
#
def result
return @result if result?
@@ -157,10 +192,12 @@
# @api private
#
# Called from at_exit block
#
def run_exit_tasks!
+ set_exit_exception
+
exit_status = SimpleCov.exit_status_from_exception
SimpleCov.at_exit.call
# Don't modify the exit status unless the result has already been
@@ -168,11 +205,11 @@
exit_status = SimpleCov.process_result(SimpleCov.result, exit_status) if SimpleCov.result?
# Force exit with stored status (see github issue #5)
# unless it's nil or 0 (see github issue #281)
if exit_status&.positive?
- $stderr.printf("SimpleCov failed with exit %<exit_status>d\n", :exit_status => exit_status) if print_error_status
+ $stderr.printf("SimpleCov failed with exit %<exit_status>d\n", exit_status: exit_status) if print_error_status
Kernel.exit exit_status
end
end
# @api private
@@ -195,29 +232,29 @@
def result_exit_status(result, covered_percent)
covered_percentages = result.covered_percentages.map { |percentage| percentage.floor(2) }
if covered_percent < SimpleCov.minimum_coverage
$stderr.printf(
"Coverage (%<covered>.2f%%) is below the expected minimum coverage (%<minimum_coverage>.2f%%).\n",
- :covered => covered_percent,
- :minimum_coverage => SimpleCov.minimum_coverage
+ covered: covered_percent,
+ minimum_coverage: SimpleCov.minimum_coverage
)
SimpleCov::ExitCodes::MINIMUM_COVERAGE
elsif covered_percentages.any? { |p| p < SimpleCov.minimum_coverage_by_file }
$stderr.printf(
"File (%<file>s) is only (%<least_covered_percentage>.2f%%) covered. This is below the expected minimum coverage per file of (%<min_coverage>.2f%%).\n",
- :file => result.least_covered_file,
- :least_covered_percentage => covered_percentages.min,
- :min_coverage => SimpleCov.minimum_coverage_by_file
+ file: result.least_covered_file,
+ least_covered_percentage: covered_percentages.min,
+ min_coverage: SimpleCov.minimum_coverage_by_file
)
SimpleCov::ExitCodes::MINIMUM_COVERAGE
elsif (last_run = SimpleCov::LastRun.read)
- coverage_diff = last_run["result"]["covered_percent"] - covered_percent
+ coverage_diff = last_run[:result][:covered_percent] - covered_percent
if coverage_diff > SimpleCov.maximum_coverage_drop
$stderr.printf(
"Coverage has dropped by %<drop_percent>.2f%% since the last time (maximum allowed: %<max_drop>.2f%%).\n",
- :drop_percent => coverage_diff,
- :max_drop => SimpleCov.maximum_coverage_drop
+ drop_percent: coverage_diff,
+ max_drop: SimpleCov.maximum_coverage_drop
)
SimpleCov::ExitCodes::MAXIMUM_COVERAGE_DROP
else
SimpleCov::ExitCodes::SUCCESS
end
@@ -246,22 +283,28 @@
#
# @api private
#
def write_last_run(covered_percent)
- SimpleCov::LastRun.write(:result => {:covered_percent => covered_percent})
+ SimpleCov::LastRun.write(result: {covered_percent: covered_percent})
end
private
+ def initial_setup(profile, &block)
+ load_profile(profile) if profile
+ configure(&block) if block_given?
+ self.running = true
+ end
+
#
# Trigger Coverage.start depends on given config coverage_criterion
#
# With Positive branch it supports all coverage measurement types
# With Negative branch it supports only line coverage measurement type
#
- def start_coverage_measurment
+ def start_coverage_measurement
# This blog post gives a good run down of the coverage criterias introduced
# in Ruby 2.5: https://blog.bigbinary.com/2018/04/11/ruby-2-5-supports-measuring-branch-and-method-coverages.html
# There is also a nice writeup of the different coverage criteria made in this
# comment https://github.com/colszowka/simplecov/pull/692#discussion_r281836176 :
# Ruby < 2.5:
@@ -285,14 +328,30 @@
# :branches
# :methods
# :oneshot_lines - can not be combined with lines
# :all - same as lines + branches + methods
#
- if branch_coverage?
- Coverage.start(:all)
+ if coverage_start_arguments_supported?
+ start_coverage_with_criteria
else
Coverage.start
end
+ end
+
+ def start_coverage_with_criteria
+ start_arguments = coverage_criteria.map do |criterion|
+ [lookup_corresponding_ruby_coverage_name(criterion), true]
+ end.to_h
+
+ Coverage.start(start_arguments)
+ end
+
+ CRITERION_TO_RUBY_COVERAGE = {
+ branch: :branches,
+ line: :lines
+ }.freeze
+ def lookup_corresponding_ruby_coverage_name(criterion)
+ CRITERION_TO_RUBY_COVERAGE.fetch(criterion)
end
#
# Finds files that were to be tracked but were not loaded and initializes
# the line-by-line coverage to zero (if relevant) or nil (comments / whitespace etc).