Class: Roast::Helpers::MinitestCoverageRunner

Inherits:
Object
  • Object
show all
Defined in:
lib/roast/helpers/minitest_coverage_runner.rb

Instance Method Summary collapse

Constructor Details

#initialize(test_file_path, subject_file_path) ⇒ MinitestCoverageRunner

Returns a new instance of MinitestCoverageRunner.



54
55
56
57
58
59
60
61
# File 'lib/roast/helpers/minitest_coverage_runner.rb', line 54

def initialize(test_file_path, subject_file_path)
  @test_file = File.expand_path(test_file_path)
  @subject_file = File.expand_path(subject_file_path)

  # Detect Rails vs Gem by checking for config/environment.rb or a .gemspec
  @rails_app   = File.exist?(File.join(Dir.pwd, "config", "environment.rb"))
  @gem_project = Dir.glob(File.join(Dir.pwd, "*.gemspec")).any?
end

Instance Method Details

#runObject



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/roast/helpers/minitest_coverage_runner.rb', line 63

def run
  # Make sure the test dir (and possibly the test file's dir) is on the LOAD_PATH,
  # so that 'require "test_helper"' from inside the test works in plain IRB.
  ensure_load_path_for_test

  # Start coverage
  Coverage.start(lines: true, branches: true, methods: true)

  # If Rails app, load Rails environment & test_help
  if @rails_app
    ENV["RAILS_ENV"]      = "test"
    ENV["DISABLE_SPRING"] = "1" # ensure we don't use Spring, so coverage is captured
    require File.expand_path("config/environment", Dir.pwd)
    require "rails/test_help"
  else
    require "bundler/setup"
  end

  # Now require the test file directly
  require @test_file

  # Require the source file to make sure it's loaded for coverage
  require @subject_file

  # Initialize our test stats collector - must happen before tests run
  stats_collector = TestStatsCollector.instance

  # Run Minitest tests
  # Redirect stdout to stderr for test output so that it doesn't pollute
  # the JSON output of the coverage runner
  original_stdout = $stdout.dup
  $stdout.reopen($stderr)
  test_passed = Minitest.run([])
  $stdout.reopen(original_stdout) # Restore original stdout

  # Report test stats
  test_count = stats_collector.tests_count
  assertion_count = stats_collector.assertions_count

  coverage_data = Coverage.result(stop: false)

  file_data = coverage_data[@subject_file]
  coverage_result =
    if file_data.nil?
      # If file never got loaded, coverage is effectively zero for that file
      { line: 0.0, branch: 0.0, method: 0.0, tests: test_count, assertions: assertion_count }
    else
      result = compute_coverage_stats(file_data)
      result.merge(tests: test_count, assertions: assertion_count)
    end

  # If the test run failed (returned false), exit 1
  unless test_passed
    Roast::Helpers::Logger.error("\nTest failures detected. Exiting with status 1.")
    exit(1)
  end

  puts coverage_result.to_json
end