rspec-tracer 0.9.0 → 1.0.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +28 -0
- data/README.md +41 -14
- data/lib/rspec_tracer/cache.rb +76 -36
- data/lib/rspec_tracer/configuration.rb +16 -9
- data/lib/rspec_tracer/coverage_merger.rb +41 -0
- data/lib/rspec_tracer/coverage_reporter.rb +31 -28
- data/lib/rspec_tracer/coverage_writer.rb +58 -0
- data/lib/rspec_tracer/html_reporter/reporter.rb +56 -16
- data/lib/rspec_tracer/html_reporter/views/duplicate_examples.erb +34 -0
- data/lib/rspec_tracer/html_reporter/views/examples.erb +5 -0
- data/lib/rspec_tracer/html_reporter/views/layout.erb +8 -5
- data/lib/rspec_tracer/remote_cache/validator.rb +1 -1
- data/lib/rspec_tracer/report_generator.rb +158 -0
- data/lib/rspec_tracer/report_merger.rb +81 -0
- data/lib/rspec_tracer/report_writer.rb +141 -0
- data/lib/rspec_tracer/reporter.rb +42 -174
- data/lib/rspec_tracer/rspec_runner.rb +2 -4
- data/lib/rspec_tracer/runner.rb +41 -113
- data/lib/rspec_tracer/version.rb +1 -1
- data/lib/rspec_tracer.rb +202 -29
- metadata +23 -17
data/lib/rspec_tracer.rb
CHANGED
@@ -13,11 +13,16 @@ require 'set'
|
|
13
13
|
require_relative 'rspec_tracer/configuration'
|
14
14
|
RSpecTracer.extend RSpecTracer::Configuration
|
15
15
|
|
16
|
+
require_relative 'rspec_tracer/coverage_merger'
|
16
17
|
require_relative 'rspec_tracer/coverage_reporter'
|
18
|
+
require_relative 'rspec_tracer/coverage_writer'
|
17
19
|
require_relative 'rspec_tracer/defaults'
|
18
20
|
require_relative 'rspec_tracer/example'
|
19
21
|
require_relative 'rspec_tracer/html_reporter/reporter'
|
20
22
|
require_relative 'rspec_tracer/remote_cache/cache'
|
23
|
+
require_relative 'rspec_tracer/report_generator'
|
24
|
+
require_relative 'rspec_tracer/report_merger'
|
25
|
+
require_relative 'rspec_tracer/report_writer'
|
21
26
|
require_relative 'rspec_tracer/rspec_reporter'
|
22
27
|
require_relative 'rspec_tracer/rspec_runner'
|
23
28
|
require_relative 'rspec_tracer/ruby_coverage'
|
@@ -34,10 +39,12 @@ module RSpecTracer
|
|
34
39
|
RSpecTracer.running = false
|
35
40
|
RSpecTracer.pid = Process.pid
|
36
41
|
|
37
|
-
|
42
|
+
return if RUBY_ENGINE == 'jruby' && !valid_jruby_opts?
|
38
43
|
|
39
|
-
|
44
|
+
puts "Started RSpec tracer (pid: #{RSpecTracer.pid})"
|
40
45
|
|
46
|
+
parallel_tests_setup
|
47
|
+
configure(&block) if block
|
41
48
|
initial_setup
|
42
49
|
end
|
43
50
|
|
@@ -67,6 +74,8 @@ module RSpecTracer
|
|
67
74
|
end
|
68
75
|
end
|
69
76
|
|
77
|
+
runner.deregister_duplicate_examples
|
78
|
+
|
70
79
|
[to_run, groups.to_a]
|
71
80
|
end
|
72
81
|
# rubocop:enable Metrics/AbcSize
|
@@ -74,10 +83,12 @@ module RSpecTracer
|
|
74
83
|
def at_exit_behavior
|
75
84
|
return unless RSpecTracer.pid == Process.pid && RSpecTracer.running
|
76
85
|
|
77
|
-
::Kernel.exit(1) if runner.incorrect_analysis?
|
78
|
-
|
79
86
|
run_exit_tasks
|
87
|
+
|
88
|
+
::Kernel.exit(1) if runner.non_zero_exit_code?
|
80
89
|
ensure
|
90
|
+
FileUtils.rm_f(RSpecTracer.parallel_tests_lock_file) if parallel_tests_last_process?
|
91
|
+
|
81
92
|
RSpecTracer.running = false
|
82
93
|
end
|
83
94
|
|
@@ -107,6 +118,14 @@ module RSpecTracer
|
|
107
118
|
return @coverage_reporter if defined?(@coverage_reporter)
|
108
119
|
end
|
109
120
|
|
121
|
+
def coverage_merger
|
122
|
+
return @coverage_merger if defined?(@coverage_merger)
|
123
|
+
end
|
124
|
+
|
125
|
+
def report_merger
|
126
|
+
return @report_merger if defined?(@report_merger)
|
127
|
+
end
|
128
|
+
|
110
129
|
def trace_point
|
111
130
|
return @trace_point if defined?(@trace_point)
|
112
131
|
end
|
@@ -123,8 +142,28 @@ module RSpecTracer
|
|
123
142
|
return @simplecov if defined?(@simplecov)
|
124
143
|
end
|
125
144
|
|
145
|
+
def parallel_tests?
|
146
|
+
return @parallel_tests if defined?(@parallel_tests)
|
147
|
+
end
|
148
|
+
|
126
149
|
private
|
127
150
|
|
151
|
+
def valid_jruby_opts?
|
152
|
+
require 'jruby'
|
153
|
+
|
154
|
+
return true if Java::OrgJruby::RubyInstanceConfig.FULL_TRACE_ENABLED &&
|
155
|
+
JRuby.runtime.object_space_enabled?
|
156
|
+
|
157
|
+
puts <<-WARN.strip.gsub(/\s+/, ' ')
|
158
|
+
RSpec Tracer is not running as it requires debug and object space enabled. Use
|
159
|
+
command line options "--debug" and "-X+O" or set the "debug.fullTrace=true" and
|
160
|
+
"objectspace.enabled=true" options in your .jrubyrc file. You can also use
|
161
|
+
JRUBY_OPTS="--debug -X+O".
|
162
|
+
WARN
|
163
|
+
|
164
|
+
false
|
165
|
+
end
|
166
|
+
|
128
167
|
def initial_setup
|
129
168
|
unless setup_rspec
|
130
169
|
puts 'Could not find a running RSpec process'
|
@@ -139,6 +178,36 @@ module RSpecTracer
|
|
139
178
|
@coverage_reporter = RSpecTracer::CoverageReporter.new
|
140
179
|
end
|
141
180
|
|
181
|
+
def parallel_tests_setup
|
182
|
+
@parallel_tests = !(ENV['TEST_ENV_NUMBER'] && ENV['PARALLEL_TEST_GROUPS']).nil?
|
183
|
+
|
184
|
+
return unless parallel_tests?
|
185
|
+
|
186
|
+
require 'parallel_tests' unless defined?(ParallelTests)
|
187
|
+
|
188
|
+
@coverage_merger = RSpecTracer::CoverageMerger.new
|
189
|
+
@report_merger = RSpecTracer::ReportMerger.new
|
190
|
+
rescue LoadError => e
|
191
|
+
puts "Failed to load parallel tests (Error: #{e.message})"
|
192
|
+
ensure
|
193
|
+
track_parallel_tests_test_env_number
|
194
|
+
end
|
195
|
+
|
196
|
+
def track_parallel_tests_test_env_number
|
197
|
+
return unless parallel_tests?
|
198
|
+
|
199
|
+
File.open(RSpecTracer.parallel_tests_lock_file, File::RDWR | File::CREAT, 0o644) do |f|
|
200
|
+
f.flock(File::LOCK_EX)
|
201
|
+
|
202
|
+
test_num = [f.read.to_i, ENV['TEST_ENV_NUMBER'].to_i].max
|
203
|
+
|
204
|
+
f.rewind
|
205
|
+
f.write("#{test_num}\n")
|
206
|
+
f.flush
|
207
|
+
f.truncate(f.pos)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
142
211
|
def setup_rspec
|
143
212
|
runners = ObjectSpace.each_object(::RSpec::Core::Runner) do |runner|
|
144
213
|
runner_clazz = runner.singleton_class
|
@@ -182,28 +251,37 @@ module RSpecTracer
|
|
182
251
|
end
|
183
252
|
|
184
253
|
simplecov? ? run_simplecov_exit_task : run_coverage_exit_task
|
254
|
+
|
255
|
+
run_parallel_tests_exit_tasks
|
185
256
|
end
|
186
257
|
|
187
258
|
def generate_reports
|
188
|
-
puts
|
259
|
+
puts "RSpec tracer is generating reports (pid: #{RSpecTracer.pid})"
|
189
260
|
|
190
261
|
process_dependency
|
191
262
|
process_coverage
|
192
|
-
|
193
|
-
RSpecTracer::
|
263
|
+
|
264
|
+
RSpecTracer::ReportGenerator.new(runner.reporter, runner.cache).generate_report
|
265
|
+
|
266
|
+
report_writer = RSpecTracer::ReportWriter.new(RSpecTracer.cache_path, runner.reporter)
|
267
|
+
report_writer.write_report
|
268
|
+
report_writer.print_duplicate_examples
|
269
|
+
|
270
|
+
RSpecTracer::HTMLReporter::Reporter.new(RSpecTracer.report_path, runner.reporter).generate_report
|
194
271
|
end
|
195
272
|
|
196
273
|
def process_dependency
|
197
274
|
starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
198
275
|
|
276
|
+
runner.register_interrupted_examples
|
199
277
|
runner.register_deleted_examples
|
200
278
|
runner.register_dependency(coverage_reporter.examples_coverage)
|
201
279
|
runner.register_untraced_dependency(@traced_files)
|
202
280
|
|
203
281
|
ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
204
|
-
|
282
|
+
elapsed = RSpecTracer::TimeFormatter.format_time(ending - starting)
|
205
283
|
|
206
|
-
puts "RSpec tracer processed dependency (took #{
|
284
|
+
puts "RSpec tracer processed dependency (took #{elapsed})" if RSpecTracer.verbose?
|
207
285
|
end
|
208
286
|
|
209
287
|
def process_coverage
|
@@ -214,9 +292,9 @@ module RSpecTracer
|
|
214
292
|
runner.register_examples_coverage(coverage_reporter.examples_coverage)
|
215
293
|
|
216
294
|
ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
217
|
-
|
295
|
+
elapsed = RSpecTracer::TimeFormatter.format_time(ending - starting)
|
218
296
|
|
219
|
-
puts "RSpec tracer processed coverage (took #{
|
297
|
+
puts "RSpec tracer processed coverage (took #{elapsed})" if RSpecTracer.verbose?
|
220
298
|
end
|
221
299
|
|
222
300
|
def run_simplecov_exit_task
|
@@ -236,34 +314,129 @@ module RSpecTracer
|
|
236
314
|
coverage_reporter.generate_final_coverage
|
237
315
|
|
238
316
|
file_name = File.join(RSpecTracer.coverage_path, 'coverage.json')
|
317
|
+
coverage_writer = RSpecTracer::CoverageWriter.new(file_name, coverage_reporter)
|
239
318
|
|
240
|
-
|
319
|
+
coverage_writer.write_report
|
241
320
|
|
242
321
|
ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
243
|
-
elpased = RSpecTracer::TimeFormatter.format_time(ending - starting)
|
244
322
|
|
245
|
-
|
323
|
+
coverage_writer.print_stats(ending - starting)
|
246
324
|
end
|
247
325
|
|
248
|
-
def
|
249
|
-
|
250
|
-
RSpecTracer: {
|
251
|
-
coverage: coverage_reporter.coverage,
|
252
|
-
timestamp: Time.now.utc.to_i
|
253
|
-
}
|
254
|
-
}
|
326
|
+
def run_parallel_tests_exit_tasks
|
327
|
+
return unless parallel_tests_executed?
|
255
328
|
|
256
|
-
|
329
|
+
merge_parallel_tests_reports
|
330
|
+
write_parallel_tests_merged_report
|
331
|
+
merge_parallel_tests_coverage_reports
|
332
|
+
write_parallel_tests_coverage_report
|
333
|
+
purge_parallel_tests_reports
|
257
334
|
end
|
258
335
|
|
259
|
-
def
|
260
|
-
|
336
|
+
def merge_parallel_tests_reports
|
337
|
+
return unless parallel_tests_executed?
|
338
|
+
|
339
|
+
starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
340
|
+
reports_dir = []
|
341
|
+
|
342
|
+
1.upto(ENV['PARALLEL_TEST_GROUPS'].to_i) do |test_num|
|
343
|
+
cache_path = File.dirname(RSpecTracer.cache_path)
|
344
|
+
cache_dir = File.join(cache_path, "parallel_tests_#{test_num}")
|
345
|
+
|
346
|
+
next unless File.directory?(cache_dir)
|
347
|
+
|
348
|
+
run_id = JSON.parse(File.read(File.join(cache_dir, 'last_run.json')))['run_id']
|
349
|
+
|
350
|
+
reports_dir << File.join(cache_dir, run_id)
|
351
|
+
end
|
352
|
+
|
353
|
+
report_merger.merge(reports_dir)
|
354
|
+
|
355
|
+
ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
356
|
+
elapsed = RSpecTracer::TimeFormatter.format_time(ending - starting)
|
357
|
+
|
358
|
+
puts "\nRSpec tracer merged parallel tests reports (took #{elapsed})"
|
359
|
+
end
|
360
|
+
|
361
|
+
def write_parallel_tests_merged_report
|
362
|
+
return unless parallel_tests_executed?
|
363
|
+
|
364
|
+
report_dir = File.dirname(RSpecTracer.cache_path)
|
365
|
+
|
366
|
+
RSpecTracer::ReportWriter.new(report_dir, report_merger).write_report
|
367
|
+
|
368
|
+
report_dir = File.dirname(RSpecTracer.report_path)
|
369
|
+
|
370
|
+
RSpecTracer::HTMLReporter::Reporter.new(report_dir, report_merger).generate_report
|
371
|
+
end
|
372
|
+
|
373
|
+
def merge_parallel_tests_coverage_reports
|
374
|
+
return unless parallel_tests_executed? && !simplecov?
|
375
|
+
|
376
|
+
starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
377
|
+
reports_dir = []
|
378
|
+
|
379
|
+
1.upto(ENV['PARALLEL_TEST_GROUPS'].to_i) do |test_num|
|
380
|
+
coverage_path = File.dirname(RSpecTracer.coverage_path)
|
381
|
+
coverage_dir = File.join(coverage_path, "parallel_tests_#{test_num}")
|
382
|
+
|
383
|
+
reports_dir << coverage_dir if File.directory?(coverage_dir)
|
384
|
+
end
|
385
|
+
|
386
|
+
coverage_merger.merge(reports_dir)
|
387
|
+
|
388
|
+
ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
389
|
+
elapsed = RSpecTracer::TimeFormatter.format_time(ending - starting)
|
390
|
+
|
391
|
+
puts "RSpec tracer merged parallel tests coverage reports (took #{elapsed})"
|
392
|
+
end
|
393
|
+
|
394
|
+
def write_parallel_tests_coverage_report
|
395
|
+
return unless parallel_tests_executed? && !simplecov?
|
396
|
+
|
397
|
+
starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
398
|
+
|
399
|
+
coverage_path = File.dirname(RSpecTracer.coverage_path)
|
400
|
+
file_name = File.join(coverage_path, 'coverage.json')
|
401
|
+
coverage_writer = RSpecTracer::CoverageWriter.new(file_name, coverage_merger)
|
402
|
+
|
403
|
+
coverage_writer.write_report
|
404
|
+
|
405
|
+
ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
406
|
+
|
407
|
+
coverage_writer.print_stats(ending - starting)
|
408
|
+
end
|
409
|
+
|
410
|
+
def purge_parallel_tests_reports
|
411
|
+
return unless parallel_tests_executed?
|
412
|
+
|
413
|
+
1.upto(ENV['PARALLEL_TEST_GROUPS'].to_i) do |test_num|
|
414
|
+
[RSpecTracer.cache_path, RSpecTracer.coverage_path, RSpecTracer.report_path].each do |path|
|
415
|
+
FileUtils.rm_rf(File.join(File.dirname(path), "parallel_tests_#{test_num}"))
|
416
|
+
end
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
def parallel_tests_executed?
|
421
|
+
return false unless parallel_tests? && parallel_tests_last_process?
|
422
|
+
|
423
|
+
ParallelTests.wait_for_other_processes_to_finish
|
424
|
+
|
425
|
+
true
|
426
|
+
end
|
427
|
+
|
428
|
+
def parallel_tests_last_process?
|
429
|
+
return false unless parallel_tests?
|
430
|
+
|
431
|
+
max_test_num = 0
|
432
|
+
|
433
|
+
File.open(RSpecTracer.parallel_tests_lock_file, 'r') do |f|
|
434
|
+
f.flock(File::LOCK_SH)
|
435
|
+
|
436
|
+
max_test_num = f.read.to_i
|
437
|
+
end
|
261
438
|
|
262
|
-
|
263
|
-
Coverage report generated for RSpecTracer to #{file_name}. #{stat[:covered_lines]}
|
264
|
-
/ #{stat[:total_lines]} LOC (#{stat[:covered_percent]}%) covered
|
265
|
-
(took #{elpased})
|
266
|
-
REPORT
|
439
|
+
ENV['TEST_ENV_NUMBER'].to_i == max_test_num
|
267
440
|
end
|
268
441
|
end
|
269
442
|
end
|
metadata
CHANGED
@@ -1,60 +1,60 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-tracer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Abhimanyu Singh
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-10-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: docile
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '1.1'
|
20
17
|
- - ">="
|
21
18
|
- !ruby/object:Gem::Version
|
22
19
|
version: 1.1.0
|
20
|
+
- - "~>"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '1.1'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
|
-
- - "~>"
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '1.1'
|
30
27
|
- - ">="
|
31
28
|
- !ruby/object:Gem::Version
|
32
29
|
version: 1.1.0
|
30
|
+
- - "~>"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '1.1'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: rspec-core
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
|
-
- - "~>"
|
38
|
-
- !ruby/object:Gem::Version
|
39
|
-
version: '3.6'
|
40
37
|
- - ">="
|
41
38
|
- !ruby/object:Gem::Version
|
42
39
|
version: 3.6.0
|
40
|
+
- - "~>"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '3.6'
|
43
43
|
type: :runtime
|
44
44
|
prerelease: false
|
45
45
|
version_requirements: !ruby/object:Gem::Requirement
|
46
46
|
requirements:
|
47
|
-
- - "~>"
|
48
|
-
- !ruby/object:Gem::Version
|
49
|
-
version: '3.6'
|
50
47
|
- - ">="
|
51
48
|
- !ruby/object:Gem::Version
|
52
49
|
version: 3.6.0
|
50
|
+
- - "~>"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '3.6'
|
53
53
|
description: RSpec Tracer is a specs dependency analyzer, flaky tests detector, tests
|
54
54
|
accelerator, and coverage reporter tool for RSpec. It maintains a list of files
|
55
55
|
for each test, enabling itself to skip tests in the subsequent runs if none of the
|
56
56
|
dependent files are changed. It uses Ruby's built-in coverage library to keep track
|
57
|
-
of the coverage for each test
|
57
|
+
of the coverage for each test.
|
58
58
|
email:
|
59
59
|
- abhisinghabhimanyu@gmail.com
|
60
60
|
executables: []
|
@@ -67,7 +67,9 @@ files:
|
|
67
67
|
- lib/rspec_tracer.rb
|
68
68
|
- lib/rspec_tracer/cache.rb
|
69
69
|
- lib/rspec_tracer/configuration.rb
|
70
|
+
- lib/rspec_tracer/coverage_merger.rb
|
70
71
|
- lib/rspec_tracer/coverage_reporter.rb
|
72
|
+
- lib/rspec_tracer/coverage_writer.rb
|
71
73
|
- lib/rspec_tracer/defaults.rb
|
72
74
|
- lib/rspec_tracer/example.rb
|
73
75
|
- lib/rspec_tracer/filter.rb
|
@@ -90,6 +92,7 @@ files:
|
|
90
92
|
- lib/rspec_tracer/html_reporter/public/favicon.png
|
91
93
|
- lib/rspec_tracer/html_reporter/public/loading.gif
|
92
94
|
- lib/rspec_tracer/html_reporter/reporter.rb
|
95
|
+
- lib/rspec_tracer/html_reporter/views/duplicate_examples.erb
|
93
96
|
- lib/rspec_tracer/html_reporter/views/examples.erb
|
94
97
|
- lib/rspec_tracer/html_reporter/views/examples_dependency.erb
|
95
98
|
- lib/rspec_tracer/html_reporter/views/files_dependency.erb
|
@@ -100,6 +103,9 @@ files:
|
|
100
103
|
- lib/rspec_tracer/remote_cache/cache.rb
|
101
104
|
- lib/rspec_tracer/remote_cache/repo.rb
|
102
105
|
- lib/rspec_tracer/remote_cache/validator.rb
|
106
|
+
- lib/rspec_tracer/report_generator.rb
|
107
|
+
- lib/rspec_tracer/report_merger.rb
|
108
|
+
- lib/rspec_tracer/report_writer.rb
|
103
109
|
- lib/rspec_tracer/reporter.rb
|
104
110
|
- lib/rspec_tracer/rspec_reporter.rb
|
105
111
|
- lib/rspec_tracer/rspec_runner.rb
|
@@ -113,7 +119,7 @@ licenses:
|
|
113
119
|
- MIT
|
114
120
|
metadata:
|
115
121
|
homepage_uri: https://github.com/avmnu-sng/rspec-tracer
|
116
|
-
source_code_uri: https://github.com/avmnu-sng/rspec-tracer/tree/
|
122
|
+
source_code_uri: https://github.com/avmnu-sng/rspec-tracer/tree/v1.0.0
|
117
123
|
changelog_uri: https://github.com/avmnu-sng/rspec-tracer/blob/main/CHANGELOG.md
|
118
124
|
bug_tracker_uri: https://github.com/avmnu-sng/rspec-tracer/issues
|
119
125
|
post_install_message:
|
@@ -131,7 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
131
137
|
- !ruby/object:Gem::Version
|
132
138
|
version: '0'
|
133
139
|
requirements: []
|
134
|
-
rubygems_version: 3.
|
140
|
+
rubygems_version: 3.0.9
|
135
141
|
signing_key:
|
136
142
|
specification_version: 4
|
137
143
|
summary: RSpec Tracer is a specs dependency analyzer, flaky tests detector, tests
|