turbo_tests2 3.0.0 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -20,6 +20,12 @@ RSpec::Core::Runner.singleton_class.prepend(RSpecExt)
20
20
  module TurboTests
21
21
  # An RSpec formatter used for each subprocess during parallel test execution
22
22
  class JsonRowsFormatter
23
+ INTERNAL_BACKTRACE_PATTERNS = [
24
+ %r{/bin/turbo_tests2\b},
25
+ %r{/exe/turbo_tests2\b},
26
+ %r{/lib/turbo_tests(?:\.rb|/)}
27
+ ].freeze
28
+
23
29
  RSpec::Core::Formatters.register(
24
30
  self,
25
31
  :start,
@@ -31,6 +37,8 @@ module TurboTests
31
37
  :example_group_finished,
32
38
  :message,
33
39
  :seed,
40
+ :deprecation,
41
+ :dump_profile
34
42
  )
35
43
 
36
44
  attr_reader :output
@@ -42,78 +50,115 @@ module TurboTests
42
50
  def start(notification)
43
51
  output_row(
44
52
  type: :load_summary,
45
- summary: load_summary_to_json(notification),
53
+ summary: load_summary_to_json(notification)
46
54
  )
47
55
  end
48
56
 
49
57
  def example_group_started(notification)
50
58
  output_row(
51
59
  type: :group_started,
52
- group: group_to_json(notification),
60
+ group: group_to_json(notification)
53
61
  )
54
62
  end
55
63
 
56
64
  def example_group_finished(notification)
57
65
  output_row(
58
66
  type: :group_finished,
59
- group: group_to_json(notification),
67
+ group: group_to_json(notification)
60
68
  )
61
69
  end
62
70
 
63
71
  def example_passed(notification)
64
72
  output_row(
65
73
  type: :example_passed,
66
- example: example_to_json(notification.example),
74
+ example: example_to_json(notification.example)
67
75
  )
68
76
  end
69
77
 
70
78
  def example_pending(notification)
71
79
  output_row(
72
80
  type: :example_pending,
73
- example: example_to_json(notification.example),
81
+ example: example_to_json(notification.example)
74
82
  )
75
83
  end
76
84
 
77
85
  def example_failed(notification)
78
86
  output_row(
79
87
  type: :example_failed,
80
- example: example_to_json(notification.example),
88
+ example: example_to_json(notification.example)
81
89
  )
82
90
  end
83
91
 
84
92
  def seed(notification)
85
93
  output_row(
86
94
  type: :seed,
87
- seed: notification.seed,
95
+ seed: notification.seed
88
96
  )
89
97
  end
90
98
 
91
99
  def close(_notification)
92
100
  output_row(
93
- type: :close,
101
+ type: :close
94
102
  )
95
103
  end
96
104
 
97
105
  def message(notification)
98
106
  output_row(
99
107
  type: :message,
100
- message: notification.message,
108
+ message: notification.message
109
+ )
110
+ end
111
+
112
+ def deprecation(notification)
113
+ output_row(
114
+ type: :deprecation,
115
+ deprecation: deprecation_to_json(notification)
116
+ )
117
+ end
118
+
119
+ def dump_profile(notification)
120
+ output_row(
121
+ type: :profile,
122
+ profile: profile_to_json(notification)
101
123
  )
102
124
  end
103
125
 
104
126
  private
105
127
 
128
+ def profile_to_json(notification)
129
+ {
130
+ duration: notification.duration,
131
+ number_of_examples: notification.number_of_examples,
132
+ examples: notification.examples.map { |example| example_to_json(example) }
133
+ }
134
+ end
135
+
136
+ def deprecation_to_json(notification)
137
+ {
138
+ deprecated: notification.deprecated,
139
+ message: notification.message,
140
+ replacement: notification.replacement,
141
+ call_site: notification.call_site
142
+ }
143
+ end
144
+
106
145
  def exception_to_json(exception)
107
146
  return unless exception
108
147
 
109
148
  {
110
149
  class_name: exception.class.name.to_s,
111
- backtrace: exception.backtrace,
150
+ backtrace: filtered_backtrace(exception.backtrace),
112
151
  message: exception.message,
113
- cause: exception_to_json(exception.cause),
152
+ cause: exception_to_json(exception.cause)
114
153
  }
115
154
  end
116
155
 
156
+ def filtered_backtrace(backtrace)
157
+ Array(backtrace).reject do |line|
158
+ INTERNAL_BACKTRACE_PATTERNS.any? { |pattern| line.match?(pattern) }
159
+ end
160
+ end
161
+
117
162
  def execution_result_to_json(result)
118
163
  {
119
164
  example_skipped?: result.example_skipped?,
@@ -121,13 +166,14 @@ module TurboTests
121
166
  status: result.status,
122
167
  pending_fixed?: result.pending_fixed?,
123
168
  exception: exception_to_json(result.exception || result.pending_exception),
169
+ run_time: result.respond_to?(:run_time) ? result.run_time : nil
124
170
  }
125
171
  end
126
172
 
127
173
  def stack_frame_to_json(frame)
128
174
  {
129
175
  shared_group_name: frame.shared_group_name,
130
- inclusion_location: frame.inclusion_location,
176
+ inclusion_location: frame.inclusion_location
131
177
  }
132
178
  end
133
179
 
@@ -142,29 +188,29 @@ module TurboTests
142
188
  example
143
189
  .metadata[:shared_group_inclusion_backtrace]
144
190
  .map { |frame| stack_frame_to_json(frame) },
145
- extra_failure_lines: example.metadata[:extra_failure_lines],
191
+ extra_failure_lines: example.metadata[:extra_failure_lines]
146
192
  },
147
- location_rerun_argument: example.location_rerun_argument,
193
+ location_rerun_argument: example.location_rerun_argument
148
194
  }
149
195
  end
150
196
 
151
197
  def load_summary_to_json(notification)
152
198
  {
153
199
  count: notification.count,
154
- load_time: notification.load_time,
200
+ load_time: notification.load_time
155
201
  }
156
202
  end
157
203
 
158
204
  def group_to_json(notification)
159
205
  {
160
206
  group: {
161
- description: notification.group.description,
162
- },
207
+ description: notification.group.description
208
+ }
163
209
  }
164
210
  end
165
211
 
166
212
  def output_row(obj)
167
- output.puts ENV["RSPEC_FORMATTER_OUTPUT_ID"] + obj.to_json
213
+ output.puts "#{ENV.fetch("RSPEC_FORMATTER_OUTPUT_ID", "")}#{obj.to_json}"
168
214
  output.flush
169
215
  end
170
216
  end
@@ -75,7 +75,7 @@ module TurboTests
75
75
  delegate_to_formatters(:seed, RSpec::Core::Notifications::SeedNotification.new(@seed, @seed_used))
76
76
  delegate_to_formatters(
77
77
  :start,
78
- RSpec::Core::Notifications::StartNotification.new(expected_example_count, @load_time),
78
+ RSpec::Core::Notifications::StartNotification.new(expected_example_count, @load_time)
79
79
  )
80
80
  end
81
81
 
@@ -127,6 +127,27 @@ module TurboTests
127
127
  message(error_message)
128
128
  end
129
129
 
130
+ def deprecation(deprecation)
131
+ notification = RSpec::Core::Notifications::DeprecationNotification.from_hash(
132
+ deprecated: deprecation[:deprecated],
133
+ message: deprecation[:message],
134
+ replacement: deprecation[:replacement],
135
+ call_site: deprecation[:call_site]
136
+ )
137
+ delegate_to_formatters(:deprecation, notification)
138
+ end
139
+
140
+ def profile(profile)
141
+ examples = profile[:examples].map { |example| FakeExample.from_obj(example) }
142
+ notification = RSpec::Core::Notifications::ProfileNotification.new(
143
+ profile[:duration],
144
+ examples,
145
+ profile[:number_of_examples],
146
+ {}
147
+ )
148
+ delegate_to_formatters(:dump_profile, notification)
149
+ end
150
+
130
151
  def finish
131
152
  end_time = RSpec::Core::Time.now
132
153
 
@@ -137,14 +158,14 @@ module TurboTests
137
158
  delegate_to_formatters(
138
159
  :dump_pending,
139
160
  RSpec::Core::Notifications::ExamplesNotification.new(
140
- self,
141
- ),
161
+ self
162
+ )
142
163
  )
143
164
  delegate_to_formatters(
144
165
  :dump_failures,
145
166
  RSpec::Core::Notifications::ExamplesNotification.new(
146
- self,
147
- ),
167
+ self
168
+ )
148
169
  )
149
170
  delegate_to_formatters(
150
171
  :dump_summary,
@@ -154,15 +175,15 @@ module TurboTests
154
175
  @failed_examples,
155
176
  @pending_examples,
156
177
  @load_time,
157
- @errors_outside_of_examples_count,
158
- ),
178
+ @errors_outside_of_examples_count
179
+ )
159
180
  )
160
181
  delegate_to_formatters(
161
182
  :seed,
162
183
  RSpec::Core::Notifications::SeedNotification.new(
163
184
  @seed,
164
- @seed_used,
165
- ),
185
+ @seed_used
186
+ )
166
187
  )
167
188
  ensure
168
189
  delegate_to_formatters(:close, RSpec::Core::Notifications::NullNotification)
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "json"
4
4
  require "parallel_tests/rspec/runner"
5
+ require "tempfile"
5
6
 
6
7
  require_relative "../utils/hash_extension"
7
8
 
@@ -29,6 +30,7 @@ module TurboTests
29
30
 
30
31
  start_time = opts.fetch(:start_time) { RSpec::Core::Time.now }
31
32
  runtime_log = opts.fetch(:runtime_log, nil)
33
+ example_status_log = opts.fetch(:example_status_log, nil)
32
34
  verbose = opts.fetch(:verbose, false)
33
35
  fail_fast = opts.fetch(:fail_fast, nil)
34
36
  count = opts.fetch(:count, nil)
@@ -39,7 +41,10 @@ module TurboTests
39
41
 
40
42
  use_runtime_info = files == ["spec"]
41
43
 
42
- if use_runtime_info
44
+ if example_status_log
45
+ runtime_log = runtime_log_from_example_status(example_status_log)
46
+ parallel_options[:runtime_log] = runtime_log
47
+ elsif use_runtime_info
43
48
  parallel_options[:runtime_log] = runtime_log
44
49
  else
45
50
  parallel_options[:group_by] = :filesize
@@ -56,6 +61,7 @@ module TurboTests
56
61
  files: files,
57
62
  tags: tags,
58
63
  runtime_log: runtime_log,
64
+ example_status_log: example_status_log,
59
65
  verbose: verbose,
60
66
  fail_fast: fail_fast,
61
67
  count: count,
@@ -64,9 +70,24 @@ module TurboTests
64
70
  print_failed_group: print_failed_group,
65
71
  use_runtime_info: use_runtime_info,
66
72
  parallel_options: parallel_options,
67
- nice: nice,
73
+ nice: nice
68
74
  ).run
69
75
  end
76
+
77
+ def runtime_log_from_example_status(example_status_log)
78
+ statuses = RSpec::Core::ExampleStatusPersister.load_from(example_status_log)
79
+ runtimes = statuses.each_with_object(Hash.new(0.0)) do |status, sums|
80
+ next unless status.fetch(:status).match?(/pass/i)
81
+
82
+ file_name = RSpec::Core::Example.parse_id(status.fetch(:example_id)).first
83
+ sums[file_name] += status.fetch(:run_time).to_s[/\d+(\.\d+)?/].to_f
84
+ end
85
+
86
+ path = File.join("tmp", "turbo_tests2_example_status_runtime.log")
87
+ FileUtils.mkdir_p(File.dirname(path))
88
+ File.write(path, runtimes.sort.map { |file, runtime| "#{file}:#{runtime}" }.join("\n"))
89
+ path
90
+ end
70
91
  end
71
92
 
72
93
  def initialize(**opts)
@@ -97,6 +118,7 @@ module TurboTests
97
118
  @messages = Thread::Queue.new
98
119
  @threads = []
99
120
  @wait_threads = []
121
+ @exited_process_ids = []
100
122
  @error = false
101
123
  @print_failed_group = opts[:print_failed_group]
102
124
  end
@@ -104,41 +126,44 @@ module TurboTests
104
126
  def run
105
127
  @num_processes = [
106
128
  ParallelTests.determine_number_of_processes(@count),
107
- ParallelTests::RSpec::Runner.tests_with_size(@files, {}).size,
129
+ ParallelTests::RSpec::Runner.tests_with_size(@files, {}).size
108
130
  ].min
109
131
 
110
132
  tests_in_groups =
111
133
  ParallelTests::RSpec::Runner.tests_in_groups(
112
134
  @files,
113
135
  @num_processes,
114
- **@parallel_options,
136
+ **@parallel_options
115
137
  )
138
+ @tests_in_groups = tests_in_groups
116
139
 
117
140
  subprocess_opts = {
118
- record_runtime: @record_runtime,
141
+ record_runtime: @record_runtime
119
142
  }
120
143
 
121
- @reporter.report(tests_in_groups) do |_reporter|
122
- old_signal = Signal.trap(:INT) { handle_interrupt }
144
+ ParallelTests.with_pid_file do
145
+ @reporter.report(tests_in_groups) do |_reporter|
146
+ old_signal = Signal.trap(:INT) { handle_interrupt }
123
147
 
124
- @wait_threads = tests_in_groups.map.with_index do |tests, process_id|
125
- start_regular_subprocess(tests, process_id + 1, **subprocess_opts)
126
- end.compact
127
- @interrupt_handled = false
148
+ @wait_threads = tests_in_groups.map.with_index do |tests, process_id|
149
+ start_regular_subprocess(tests, process_id + 1, **subprocess_opts)
150
+ end.compact
151
+ @interrupt_handled = false
128
152
 
129
- handle_messages
153
+ handle_messages
130
154
 
131
- @threads.each(&:join)
155
+ @threads.each(&:join)
132
156
 
133
- report_failed_group(tests_in_groups) if @print_failed_group
157
+ report_failed_group(tests_in_groups) if @print_failed_group
134
158
 
135
- Signal.trap(:INT, old_signal)
159
+ Signal.trap(:INT, old_signal)
136
160
 
137
- if @reporter.failed_examples.empty? && @wait_threads.map(&:value).all?(&:success?)
138
- 0
139
- else
140
- # From https://github.com/galtzo-floss/turbo_tests2/pull/20/
141
- @wait_threads.map { |thread| thread.value.exitstatus }.max
161
+ if @reporter.failed_examples.empty? && @wait_threads.map(&:value).all?(&:success?)
162
+ 0
163
+ else
164
+ # From https://github.com/galtzo-floss/turbo_tests2/pull/20/
165
+ @wait_threads.map { |thread| thread.value.exitstatus }.max
166
+ end
142
167
  end
143
168
  end
144
169
  end
@@ -150,6 +175,7 @@ module TurboTests
150
175
  Kernel.exit
151
176
  else
152
177
  puts "\nShutting down subprocesses..."
178
+ report_unfinished_groups("Groups not finished")
153
179
  @wait_threads.each do |wait_thr|
154
180
  begin
155
181
  child_pid = wait_thr.pid
@@ -165,11 +191,15 @@ module TurboTests
165
191
 
166
192
  def start_regular_subprocess(tests, process_id, **opts)
167
193
  start_subprocess(
168
- {"TEST_ENV_NUMBER" => process_id.to_s},
194
+ {
195
+ "TEST_ENV_NUMBER" => process_id.to_s,
196
+ "PARALLEL_TEST_GROUPS" => @num_processes.to_s,
197
+ "PARALLEL_PID_FILE" => parallel_pid_file_path
198
+ },
169
199
  @tags.map { |tag| "--tag=#{tag}" },
170
200
  tests,
171
201
  process_id,
172
- **opts,
202
+ **opts
173
203
  )
174
204
  end
175
205
 
@@ -177,7 +207,7 @@ module TurboTests
177
207
  if tests.empty?
178
208
  @messages << {
179
209
  type: "exit",
180
- process_id: process_id,
210
+ process_id: process_id
181
211
  }
182
212
 
183
213
  nil
@@ -201,7 +231,7 @@ module TurboTests
201
231
  "--format",
202
232
  "ParallelTests::RSpec::RuntimeLogger",
203
233
  "--out",
204
- @runtime_log,
234
+ @runtime_log
205
235
  ]
206
236
  else
207
237
  []
@@ -209,7 +239,7 @@ module TurboTests
209
239
 
210
240
  seed_option = if @seed_used
211
241
  [
212
- "--seed", @seed,
242
+ "--seed", @seed
213
243
  ]
214
244
  else
215
245
  []
@@ -225,20 +255,22 @@ module TurboTests
225
255
  "TurboTests::JsonRowsFormatter",
226
256
  *record_runtime_options,
227
257
  *spec_opts,
228
- *tests,
258
+ *tests
229
259
  ]
230
260
  command.unshift("nice") if @nice
231
261
 
232
262
  if @verbose
233
263
  command_str = [
234
264
  env.map { |k, v| "#{k}=#{v}" }.join(" "),
235
- command.join(" "),
265
+ command.join(" ")
236
266
  ].select { |x| x.size > 0 }.join(" ")
237
267
 
238
268
  warn("Process #{process_id}: #{command_str}")
239
269
  end
240
270
 
271
+ pid_file_path = env["PARALLEL_PID_FILE"] || parallel_pid_file_path
241
272
  stdin, stdout, stderr, wait_thr = Open3.popen3(env, *command)
273
+ track_parallel_pid(wait_thr.pid, pid_file_path)
242
274
  stdin.close
243
275
 
244
276
  # rubocop:disable ThreadSafety/NewThread
@@ -267,7 +299,12 @@ module TurboTests
267
299
 
268
300
  # rubocop:disable ThreadSafety/NewThread
269
301
  @threads << Thread.new do
270
- @messages << {type: "error"} unless wait_thr.value.success?
302
+ begin
303
+ status = wait_thr.value
304
+ @messages << {type: "error"} unless status.success?
305
+ ensure
306
+ untrack_parallel_pid(wait_thr.pid, pid_file_path)
307
+ end
271
308
  end
272
309
  # rubocop:enable ThreadSafety/NewThread
273
310
 
@@ -275,6 +312,18 @@ module TurboTests
275
312
  end
276
313
  end
277
314
 
315
+ def parallel_pid_file_path
316
+ ENV["PARALLEL_PID_FILE"]
317
+ end
318
+
319
+ def track_parallel_pid(pid, pid_file_path = parallel_pid_file_path)
320
+ ParallelTests::Pids.new(pid_file_path).add(pid) if pid && pid_file_path
321
+ end
322
+
323
+ def untrack_parallel_pid(pid, pid_file_path = parallel_pid_file_path)
324
+ ParallelTests::Pids.new(pid_file_path).delete(pid) if pid && pid_file_path
325
+ end
326
+
278
327
  def start_copy_thread(src, dst)
279
328
  # rubocop:disable ThreadSafety/NewThread
280
329
  Thread.new do
@@ -318,6 +367,7 @@ module TurboTests
318
367
  @reporter.example_failed(example)
319
368
  @failure_count += 1
320
369
  if fail_fast_met
370
+ report_unfinished_groups("Groups stopped by fail-fast")
321
371
  @threads.each(&:kill)
322
372
  break
323
373
  end
@@ -328,13 +378,16 @@ module TurboTests
328
378
  else
329
379
  @reporter.message(message[:message])
330
380
  end
331
- when "seed"
332
- when "close"
333
- when "error"
381
+ when "deprecation"
382
+ @reporter.deprecation(message[:deprecation])
383
+ when "profile"
384
+ @reporter.profile(message[:profile])
385
+ when "seed", "close", "error"
334
386
  # Do nothing
335
387
  nil
336
388
  when "exit"
337
389
  exited += 1
390
+ @exited_process_ids << message[:process_id]
338
391
  break if exited == @num_processes
339
392
  else
340
393
  warn("Unhandled message in main process: #{message}")
@@ -357,5 +410,20 @@ module TurboTests
357
410
  puts "Group that failed: #{failing_group}"
358
411
  end
359
412
  end
413
+
414
+ def report_unfinished_groups(label)
415
+ groups = Array(@tests_in_groups)
416
+ unfinished_groups = groups.each_with_index.with_object([]) do |(tests, index), unfinished|
417
+ process_id = index + 1
418
+ unfinished << tests unless @exited_process_ids.include?(process_id)
419
+ end
420
+
421
+ return if unfinished_groups.empty?
422
+
423
+ puts "#{label}:"
424
+ unfinished_groups.each_with_index do |tests, index|
425
+ puts " #{index + 1}) #{tests.join(" ")}"
426
+ end
427
+ end
360
428
  end
361
429
  end
@@ -2,7 +2,16 @@
2
2
 
3
3
  module TurboTests
4
4
  class Shim
5
- Result = Struct.new(:status, :path, :message, :exit_code, keyword_init: true)
5
+ class Result
6
+ attr_reader :status, :path, :message, :exit_code
7
+
8
+ def initialize(status:, path:, message:, exit_code:)
9
+ @status = status
10
+ @path = path
11
+ @message = message
12
+ @exit_code = exit_code
13
+ end
14
+ end
6
15
 
7
16
  DEFAULT_RELATIVE_PATH = File.join("bin", "turbo_tests")
8
17
  MANAGED_MARKER = "Generated by turbo_tests2 shim install"
@@ -2,7 +2,7 @@
2
2
 
3
3
  module TurboTests
4
4
  module Version
5
- VERSION = "3.0.0"
5
+ VERSION = "3.1.1"
6
6
  end
7
7
  VERSION = Version::VERSION # Traditional Constant Location
8
8
  end
data/lib/turbo_tests.rb CHANGED
@@ -39,7 +39,7 @@ module TurboTests
39
39
  klass.new(
40
40
  obj[:backtrace],
41
41
  obj[:message],
42
- FakeException.from_obj(obj[:cause]),
42
+ FakeException.from_obj(obj[:cause])
43
43
  )
44
44
  end
45
45
  end
@@ -52,6 +52,7 @@ module TurboTests
52
52
  :pending_fixed?,
53
53
  :exception,
54
54
  :pending_exception,
55
+ :run_time
55
56
  )
56
57
  class FakeExecutionResult
57
58
  class << self
@@ -63,6 +64,7 @@ module TurboTests
63
64
  obj[:pending_fixed?],
64
65
  FakeException.from_obj(obj[:exception]),
65
66
  FakeException.from_obj(obj[:exception]),
67
+ obj[:run_time]
66
68
  )
67
69
  end
68
70
  end
@@ -74,7 +76,7 @@ module TurboTests
74
76
  :description,
75
77
  :full_description,
76
78
  :metadata,
77
- :location_rerun_argument,
79
+ :location_rerun_argument
78
80
  )
79
81
  class FakeExample
80
82
  class << self
@@ -84,7 +86,7 @@ module TurboTests
84
86
  metadata[:shared_group_inclusion_backtrace].map! do |frame|
85
87
  RSpec::Core::SharedExampleGroupInclusionStackFrame.new(
86
88
  frame[:shared_group_name],
87
- frame[:inclusion_location],
89
+ frame[:inclusion_location]
88
90
  )
89
91
  end
90
92
 
@@ -96,14 +98,14 @@ module TurboTests
96
98
  obj[:description],
97
99
  obj[:full_description],
98
100
  metadata,
99
- obj[:location_rerun_argument],
101
+ obj[:location_rerun_argument]
100
102
  )
101
103
  end
102
104
  end
103
105
 
104
106
  def notification
105
107
  RSpec::Core::Notifications::ExampleNotification.for(
106
- self,
108
+ self
107
109
  )
108
110
  end
109
111
  end
@@ -1,26 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bundler"
4
3
  require "rspec/core"
5
4
 
6
5
  RSpec.shared_context("with simplecov spawn coverage") do
7
6
  let(:simplecov_spawn_path) do
8
- File.expand_path(".simplecov_spawn.rb", Bundler.root.to_s)
7
+ [Dir.pwd, File.expand_path("..", Dir.pwd)]
8
+ .map { |dir| File.expand_path(".simplecov_spawn.rb", dir) }
9
+ .find { |path| File.file?(path) }
9
10
  end
10
11
 
11
12
  around do |example|
12
13
  original_rubyopt = ENV.fetch("RUBYOPT", nil)
14
+ original_cov_min_hard = ENV.fetch("K_SOUP_COV_MIN_HARD", nil)
13
15
  begin
14
16
  if defined?(SimpleCov) && SimpleCov.running
15
17
  spawn_path = simplecov_spawn_path
16
18
  raise ArgumentError, "Expected SimpleCov spawn shim at #{spawn_path}" unless File.file?(spawn_path)
17
19
 
20
+ ENV["K_SOUP_COV_MIN_HARD"] = "false"
18
21
  ENV["RUBYOPT"] = ["-r#{spawn_path}", original_rubyopt].compact.join(" ").strip
19
22
  end
20
23
 
21
24
  example.run
22
25
  ensure
23
26
  ENV["RUBYOPT"] = original_rubyopt
27
+ ENV["K_SOUP_COV_MIN_HARD"] = original_cov_min_hard
24
28
  end
25
29
  end
26
30
  end
@@ -4,4 +4,3 @@ module TurboTests
4
4
  end
5
5
  VERSION: String
6
6
  end
7
-
data.tar.gz.sig CHANGED
Binary file