require "open3" module Teaspoon class Coverage def self.configuration(name = Teaspoon.configuration.use_coverage) name = normalize_config_name(name) config = Teaspoon.configuration.coverage_configs[name] raise Teaspoon::UnknownCoverage.new(name: name) unless config.present? config[:instance] ||= Teaspoon::Configuration::Coverage.new(&config[:block]) end def initialize(suite_name, data) @suite_name = suite_name @data = data @executable = Teaspoon::Instrumentation.executable @config = self.class.configuration raise Teaspoon::CoverageResultsNotFoundError unless @data end def generate_reports(&block) input_path do |input| results = [] @config.reports.each do |format| result = generate_report(input, format) results << result if ["text", "text-summary"].include?(format.to_s) end block.call(results.join("\n\n")) unless results.blank? end end def check_thresholds(&block) args = threshold_args return if args.blank? input_path do |input| result, st = Open3.capture2e(@executable, "check-coverage", *args, input.shellescape) return if st.exitstatus.zero? result = result.scan(/ERROR: .*$/).join("\n").gsub("ERROR: ", "") block.call(result) unless result.blank? end end private def self.normalize_config_name(name) return "default" if name == true name.to_s end def input_path(&block) Dir.mktmpdir do |temp_path| input_path = File.join(temp_path, "coverage.json") File.open(input_path, "w") { |f| f.write(@data.to_json) } block.call(input_path) end end def generate_report(input, format) output_path = File.join(@config.output_path, @suite_name) result, st = Open3.capture2e( @executable, "report", "--include=#{input.shellescape}", "--dir #{output_path}", format ) return result.gsub("Done", "").gsub("Using reporter [#{format}]", "").strip if st.exitstatus.zero? raise Teaspoon::DependencyError.new("Unable to generate #{format} coverage report:\n#{result}") end def threshold_args %w{statements functions branches lines}.map do |assert| threshold = @config.send(:"#{assert}") "--#{assert}=#{threshold}" if threshold end.compact end end end