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).