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.

[View source]

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

[View source]

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