knapsack_pro 5.7.0 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,453 @@
1
+ # Named _specs.rb on purpose because it hangs if run as part of `bundle exec rspec`.
2
+ # Use `bundle exec ruby spec/knapsack_pro/formatters/time_tracker_specs.rb` instead.
3
+
4
+ require 'rspec/core'
5
+ require 'knapsack_pro'
6
+ require 'stringio'
7
+ require_relative '../../../lib/knapsack_pro/formatters/time_tracker'
8
+
9
+ class TestTimeTracker
10
+ def test_single_example
11
+ KnapsackPro::Formatters::TimeTracker.define_method(:rspec_split_by_test_example?) do |_file|
12
+ false
13
+ end
14
+
15
+ spec = <<~SPEC
16
+ describe "KnapsackPro::Formatters::TimeTracker" do
17
+ it do
18
+ sleep 0.1
19
+ expect(1).to eq 1
20
+ end
21
+ end
22
+ SPEC
23
+
24
+ run_specs(spec) do |spec_paths, times|
25
+ raise unless times.size == 1
26
+ raise unless times[0]["path"] == spec_paths.first
27
+ raise unless times[0]["time_execution"] > 0.10
28
+ raise unless times[0]["time_execution"] < 0.15
29
+ end
30
+ end
31
+
32
+ def test_two_files
33
+ KnapsackPro::Formatters::TimeTracker.define_method(:rspec_split_by_test_example?) do |_file|
34
+ false
35
+ end
36
+
37
+ spec_1 = <<~SPEC
38
+ describe "KnapsackPro::Formatters::TimeTracker 1" do
39
+ it do
40
+ sleep 0.1
41
+ expect(1).to eq 1
42
+ end
43
+ end
44
+ SPEC
45
+
46
+ spec_2 = <<~SPEC
47
+ describe "KnapsackPro::Formatters::TimeTracker 2" do
48
+ it do
49
+ sleep 0.2
50
+ expect(1).to eq 1
51
+ end
52
+ end
53
+ SPEC
54
+
55
+ run_specs([spec_1, spec_2]) do |spec_paths, times|
56
+ raise unless times.size == 2
57
+ raise unless times.first["path"] == spec_paths.first
58
+ raise unless times.first["time_execution"] > 0.10
59
+ raise unless times.first["time_execution"] < 0.15
60
+ raise unless times.last["path"] == spec_paths.last
61
+ raise unless times.last["time_execution"] > 0.20
62
+ raise unless times.last["time_execution"] < 0.25
63
+ end
64
+ end
65
+
66
+ def test_failing_example
67
+ KnapsackPro::Formatters::TimeTracker.define_method(:rspec_split_by_test_example?) do |_file|
68
+ false
69
+ end
70
+
71
+ spec = <<~SPEC
72
+ describe "KnapsackPro::Formatters::TimeTracker" do
73
+ it do
74
+ sleep 0.1
75
+ expect(1).to eq 2
76
+ end
77
+ end
78
+ SPEC
79
+
80
+ run_specs(spec) do |spec_paths, times|
81
+ raise unless times.size == 1
82
+ raise unless times[0]["path"] == spec_paths.first
83
+ raise unless times[0]["time_execution"] > 0.10
84
+ raise unless times[0]["time_execution"] < 0.15
85
+ end
86
+ end
87
+
88
+ def test_pending_example
89
+ KnapsackPro::Formatters::TimeTracker.define_method(:rspec_split_by_test_example?) do |_file|
90
+ false
91
+ end
92
+
93
+ spec = <<~SPEC
94
+ describe "KnapsackPro::Formatters::TimeTracker" do
95
+ xit do
96
+ sleep 0.1
97
+ expect(1).to eq 2
98
+ end
99
+ end
100
+ SPEC
101
+
102
+ run_specs(spec) do |spec_paths, times|
103
+ raise unless times.size == 1
104
+ raise unless times[0]["path"] == spec_paths.first
105
+ raise unless times[0]["time_execution"] == 0.0
106
+ end
107
+ end
108
+
109
+ def test_multiple_top_level_groups
110
+ KnapsackPro::Formatters::TimeTracker.define_method(:rspec_split_by_test_example?) do |_file|
111
+ false
112
+ end
113
+
114
+ spec = <<~SPEC
115
+ describe "KnapsackPro::Formatters::TimeTracker 1" do
116
+ it do
117
+ sleep 0.1
118
+ expect(1).to eq 1
119
+ end
120
+ end
121
+
122
+ describe "KnapsackPro::Formatters::TimeTracker 2" do
123
+ it do
124
+ sleep 0.2
125
+ expect(1).to eq 1
126
+ end
127
+ end
128
+ SPEC
129
+
130
+ run_specs(spec) do |spec_paths, times|
131
+ raise unless times.size == 1
132
+ raise unless times[0]["path"] == spec_paths.first
133
+ raise unless times[0]["time_execution"] > 0.30
134
+ raise unless times[0]["time_execution"] < 0.35
135
+ end
136
+ end
137
+
138
+ def test_rspec_split_by_test_example
139
+ KnapsackPro::Formatters::TimeTracker.define_method(:rspec_split_by_test_example?) do |_file|
140
+ true
141
+ end
142
+
143
+ spec = <<~SPEC
144
+ describe "KnapsackPro::Formatters::TimeTracker 1" do
145
+ it do
146
+ expect(1).to eq 1
147
+ end
148
+
149
+ it do
150
+ sleep 0.1
151
+ expect(1).to eq 1
152
+ end
153
+ end
154
+
155
+ describe "KnapsackPro::Formatters::TimeTracker 2" do
156
+ it do
157
+ sleep 0.2
158
+ expect(1).to eq 1
159
+ end
160
+
161
+ it do
162
+ sleep 0.3
163
+ expect(1).to eq 1
164
+ end
165
+ end
166
+ SPEC
167
+
168
+ run_specs(spec) do |spec_paths, times|
169
+ raise unless times.size == 4
170
+ spec_path = spec_paths.first
171
+ raise unless times.find { |time| time["path"] == "#{spec_path}[1:1]" }["time_execution"] < 0.05
172
+ raise unless times.find { |time| time["path"] == "#{spec_path}[1:2]" }["time_execution"] > 0.10
173
+ raise unless times.find { |time| time["path"] == "#{spec_path}[1:2]" }["time_execution"] < 0.15
174
+ raise unless times.find { |time| time["path"] == "#{spec_path}[2:1]" }["time_execution"] > 0.20
175
+ raise unless times.find { |time| time["path"] == "#{spec_path}[2:1]" }["time_execution"] < 0.25
176
+ raise unless times.find { |time| time["path"] == "#{spec_path}[2:2]" }["time_execution"] > 0.30
177
+ raise unless times.find { |time| time["path"] == "#{spec_path}[2:2]" }["time_execution"] < 0.35
178
+ end
179
+ end
180
+
181
+ def test_hooks
182
+ KnapsackPro::Formatters::TimeTracker.define_method(:rspec_split_by_test_example?) do |_file|
183
+ false
184
+ end
185
+
186
+ spec = <<~SPEC
187
+ describe "KnapsackPro::Formatters::TimeTracker" do
188
+ before(:all) do
189
+ sleep 0.1
190
+ end
191
+
192
+ before(:each) do
193
+ sleep 0.1
194
+ end
195
+
196
+ after(:each) do
197
+ sleep 0.1
198
+ end
199
+
200
+ it do
201
+ expect(1).to eq 1
202
+ end
203
+
204
+ it do
205
+ expect(1).to eq 1
206
+ end
207
+
208
+ after(:all) do
209
+ sleep 0.1
210
+ end
211
+ end
212
+ SPEC
213
+
214
+ run_specs(spec) do |spec_paths, times|
215
+ raise unless times.size == 1
216
+ raise unless times[0]["path"] == spec_paths.first
217
+ raise unless times[0]["time_execution"] > 0.60
218
+ raise unless times[0]["time_execution"] < 0.65
219
+ end
220
+ end
221
+
222
+ def test_hooks_with_rspec_split_by_test_example
223
+ KnapsackPro::Formatters::TimeTracker.define_method(:rspec_split_by_test_example?) do |_file|
224
+ true
225
+ end
226
+
227
+ spec = <<~SPEC
228
+ describe "KnapsackPro::Formatters::TimeTracker" do
229
+ before(:all) do
230
+ sleep 0.1
231
+ end
232
+
233
+ before(:each) do
234
+ sleep 0.1
235
+ end
236
+
237
+ after(:each) do
238
+ sleep 0.1
239
+ end
240
+
241
+ it do
242
+ expect(1).to eq 1
243
+ end
244
+
245
+ it do
246
+ expect(1).to eq 1
247
+ end
248
+
249
+ after(:all) do
250
+ sleep 0.1
251
+ end
252
+ end
253
+ SPEC
254
+
255
+ run_specs(spec) do |spec_paths, times|
256
+ raise unless times.size == 2
257
+ spec_path = spec_paths.first
258
+ raise unless times.find { |time| time["path"] == "#{spec_path}[1:1]" }["time_execution"] > 0.40
259
+ raise unless times.find { |time| time["path"] == "#{spec_path}[1:1]" }["time_execution"] < 0.45
260
+ raise unless times.find { |time| time["path"] == "#{spec_path}[1:2]" }["time_execution"] > 0.40
261
+ raise unless times.find { |time| time["path"] == "#{spec_path}[1:2]" }["time_execution"] < 0.45
262
+ end
263
+ end
264
+
265
+ def test_unknown_path
266
+ KnapsackPro::Formatters::TimeTracker.class_eval do
267
+ alias_method :original_file_path_for, :file_path_for
268
+
269
+ define_method(:file_path_for) do |_example|
270
+ ""
271
+ end
272
+ end
273
+
274
+ spec = <<~SPEC
275
+ describe "KnapsackPro::Formatters::TimeTracker" do
276
+ it do
277
+ expect(1).to eq 1
278
+ end
279
+ end
280
+ SPEC
281
+
282
+ run_specs(spec) do |spec_paths, times|
283
+ raise unless times.size == 2
284
+ raise unless times[0]["path"] == "UNKNOWN_PATH"
285
+ raise unless times[1]["path"] == spec_paths.first
286
+ end
287
+
288
+ ensure
289
+ KnapsackPro::Formatters::TimeTracker.class_eval do
290
+ undef :file_path_for
291
+ alias_method :file_path_for, :original_file_path_for
292
+ end
293
+ end
294
+
295
+ def test_empty_group
296
+ KnapsackPro::Formatters::TimeTracker.define_method(:rspec_split_by_test_example?) do |_file|
297
+ false
298
+ end
299
+
300
+ spec = <<~SPEC
301
+ describe "KnapsackPro::Formatters::TimeTracker" do
302
+ end
303
+ SPEC
304
+
305
+ run_specs(spec) do |spec_paths, times|
306
+ raise unless times.size == 1
307
+ raise unless times[0]["path"] == spec_paths.first
308
+ raise unless times[0]["time_execution"] == 0.0
309
+ end
310
+ end
311
+
312
+ def test_duration
313
+ KnapsackPro::Formatters::TimeTracker.define_method(:rspec_split_by_test_example?) do |_file|
314
+ false
315
+ end
316
+
317
+ spec = <<~SPEC
318
+ describe "KnapsackPro::Formatters::TimeTracker" do
319
+ it do
320
+ expect(1).to eq 1
321
+ end
322
+ end
323
+ SPEC
324
+
325
+ run_specs(spec) do |_, _, time_tracker|
326
+ raise unless time_tracker.duration > 0.0
327
+ end
328
+ end
329
+
330
+ def test_batch_duration
331
+ KnapsackPro::Formatters::TimeTracker.define_method(:rspec_split_by_test_example?) do |_file|
332
+ false
333
+ end
334
+
335
+ spec = <<~SPEC
336
+ describe "KnapsackPro::Formatters::TimeTracker" do
337
+ it do
338
+ expect(1).to eq 1
339
+ end
340
+ end
341
+ SPEC
342
+
343
+ run_specs(spec) do |_, _, time_tracker|
344
+ raise unless time_tracker.batch_duration > 0.0
345
+ end
346
+ end
347
+
348
+ def test_unexecuted_test_files
349
+ KnapsackPro::Formatters::TimeTracker.define_method(:rspec_split_by_test_example?) do |_file|
350
+ false
351
+ end
352
+
353
+ spec = <<~SPEC
354
+ describe "KnapsackPro::Formatters::TimeTracker" do
355
+ xit do
356
+ end
357
+ end
358
+ SPEC
359
+
360
+ run_specs(spec) do |spec_paths, _, time_tracker|
361
+ unexecuted_test_files = ["foo_spec.rb", "bar_spec.rb"]
362
+ # Need to filter because RSpec keeps accumulating state.
363
+ files = time_tracker
364
+ .unexecuted_test_files(spec_paths + unexecuted_test_files)
365
+ .filter { |file| spec_paths.include?(file) || unexecuted_test_files.include?(file) }
366
+
367
+ raise unless files.size == 3
368
+ end
369
+ end
370
+
371
+ def test_subset
372
+ KnapsackPro::Formatters::TimeTracker.define_method(:rspec_split_by_test_example?) do |_file|
373
+ false
374
+ end
375
+ KnapsackPro::Formatters::TimeTracker.class_eval do
376
+ alias_method :original_stop, :stop
377
+
378
+ # In Regular Mode, #subset is called before #stop.
379
+ # This test makes #stop a noop to simulate that behavior.
380
+ define_method(:stop) do |_|
381
+ end
382
+ end
383
+
384
+ spec = <<~SPEC
385
+ describe "KnapsackPro::Formatters::TimeTracker" do
386
+ it "works" do
387
+ sleep 0.1
388
+ expect(1).to eq 1
389
+ end
390
+ end
391
+ SPEC
392
+
393
+ run_specs(spec) do |spec_paths, times, time_tracker|
394
+ # Need to filter because RSpec keeps accumulating state.
395
+ files = time_tracker
396
+ .batch
397
+ .filter { |file| spec_paths.include?(file["path"]) }
398
+
399
+ raise unless files.size == 1
400
+ raise unless files[0]["path"] == spec_paths.first
401
+ raise unless files[0]["time_execution"] > 0.10
402
+ raise unless files[0]["time_execution"] < 0.15
403
+ end
404
+
405
+ ensure
406
+ KnapsackPro::Formatters::TimeTracker.class_eval do
407
+ undef :stop
408
+ alias_method :stop, :original_stop
409
+ end
410
+ end
411
+
412
+ private
413
+
414
+ def run_specs(specs)
415
+ paths = Array(specs).map.with_index do |spec, i|
416
+ path = "spec/knapsack_pro/formatters/#{i}_#{SecureRandom.uuid}_spec.rb"
417
+ File.open(path, 'w') { |file| file.write(spec) }
418
+ path
419
+ end
420
+
421
+ options = ::RSpec::Core::ConfigurationOptions.new([
422
+ "--format", KnapsackPro::Formatters::TimeTracker.to_s,
423
+ *paths,
424
+ ])
425
+ runner = ::RSpec::Core::Runner.new(options)
426
+ runner.run(StringIO.new, StringIO.new)
427
+
428
+ time_tracker = runner.configuration.formatters.find { |f| f.class.to_s == KnapsackPro::Formatters::TimeTracker.to_s }
429
+ # Need to filter because RSpec keeps accumulating state.
430
+ times = time_tracker
431
+ .queue(paths)
432
+ .sort_by { |time| time["path"] }
433
+ .filter do |time|
434
+ paths.any? { |path| time["path"].start_with?(path) || time["path"] == "UNKNOWN_PATH" }
435
+ end
436
+ yield(paths, times, time_tracker)
437
+
438
+ ensure
439
+ paths.each { |path| File.delete(path) }
440
+ # Need to reset because RSpec keeps reusing the same instance.
441
+ time_tracker.instance_variable_set(:@queue, {}) if time_tracker
442
+ time_tracker.instance_variable_set(:@started, time_tracker.send(:now)) if time_tracker
443
+ end
444
+ end
445
+
446
+ TestTimeTracker
447
+ .instance_methods
448
+ .filter { |method| method.to_s.start_with?("test_") }
449
+ .shuffle
450
+ .each do |method|
451
+ puts method
452
+ TestTimeTracker.new.public_send(method)
453
+ end
@@ -6,6 +6,7 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
6
6
 
7
7
  require KnapsackPro.root + '/lib/knapsack_pro/formatters/rspec_queue_summary_formatter'
8
8
  require KnapsackPro.root + '/lib/knapsack_pro/formatters/rspec_queue_profile_formatter_extension'
9
+ require KnapsackPro.root + '/lib/knapsack_pro/formatters/time_tracker'
9
10
  end
10
11
 
11
12
  describe '.run' do
@@ -45,7 +46,13 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
45
46
  status: :next,
46
47
  runner: runner,
47
48
  can_initialize_queue: true,
48
- args: ['--example-arg', 'example-value', '--format', 'progress', '--format', 'KnapsackPro::Formatters::RSpecQueueSummaryFormatter', '--default-path', 'fake-test-dir'],
49
+ args: [
50
+ '--example-arg', 'example-value',
51
+ '--format', 'progress',
52
+ '--format', 'KnapsackPro::Formatters::RSpecQueueSummaryFormatter',
53
+ '--format', 'KnapsackPro::Formatters::TimeTracker',
54
+ '--default-path', 'fake-test-dir',
55
+ ],
49
56
  exitstatus: 0,
50
57
  all_test_file_paths: [],
51
58
  }
@@ -71,7 +78,12 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
71
78
  status: :next,
72
79
  runner: runner,
73
80
  can_initialize_queue: true,
74
- args: ['--format', 'documentation', '--format', 'KnapsackPro::Formatters::RSpecQueueSummaryFormatter', '--default-path', 'fake-test-dir'],
81
+ args: [
82
+ '--format', 'documentation',
83
+ '--format', 'KnapsackPro::Formatters::RSpecQueueSummaryFormatter',
84
+ '--format', 'KnapsackPro::Formatters::TimeTracker',
85
+ '--default-path', 'fake-test-dir',
86
+ ],
75
87
  exitstatus: 0,
76
88
  all_test_file_paths: [],
77
89
  }
@@ -97,7 +109,12 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
97
109
  status: :next,
98
110
  runner: runner,
99
111
  can_initialize_queue: true,
100
- args: ['-f', 'd', '--format', 'KnapsackPro::Formatters::RSpecQueueSummaryFormatter', '--default-path', 'fake-test-dir'],
112
+ args: [
113
+ '-f', 'd',
114
+ '--format', 'KnapsackPro::Formatters::RSpecQueueSummaryFormatter',
115
+ '--format', 'KnapsackPro::Formatters::TimeTracker',
116
+ '--default-path', 'fake-test-dir',
117
+ ],
101
118
  exitstatus: 0,
102
119
  all_test_file_paths: [],
103
120
  }
@@ -123,7 +140,12 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
123
140
  status: :next,
124
141
  runner: runner,
125
142
  can_initialize_queue: true,
126
- args: ['-fMyCustomFormatter', '--format', 'KnapsackPro::Formatters::RSpecQueueSummaryFormatter', '--default-path', 'fake-test-dir'],
143
+ args: [
144
+ '-fMyCustomFormatter',
145
+ '--format', 'KnapsackPro::Formatters::RSpecQueueSummaryFormatter',
146
+ '--format', 'KnapsackPro::Formatters::TimeTracker',
147
+ '--default-path', 'fake-test-dir',
148
+ ],
127
149
  exitstatus: 0,
128
150
  all_test_file_paths: [],
129
151
  }
@@ -165,7 +187,12 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
165
187
  status: :next,
166
188
  runner: runner,
167
189
  can_initialize_queue: true,
168
- args: ['--format', 'progress', '--format', 'KnapsackPro::Formatters::RSpecQueueSummaryFormatter', '--default-path', 'fake-test-dir'],
190
+ args: [
191
+ '--format', 'progress',
192
+ '--format', 'KnapsackPro::Formatters::RSpecQueueSummaryFormatter',
193
+ '--format', 'KnapsackPro::Formatters::TimeTracker',
194
+ '--default-path', 'fake-test-dir',
195
+ ],
169
196
  exitstatus: 0,
170
197
  all_test_file_paths: [],
171
198
  }
@@ -219,12 +246,7 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
219
246
 
220
247
  expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_SUBSET_QUEUE_ID', subset_queue_id)
221
248
 
222
- tracker = instance_double(KnapsackPro::Tracker)
223
- expect(KnapsackPro).to receive(:tracker).twice.and_return(tracker)
224
- expect(tracker).to receive(:reset!)
225
- expect(tracker).to receive(:set_prerun_tests).with(test_file_paths)
226
-
227
- expect(described_class).to receive(:ensure_spec_opts_have_rspec_queue_summary_formatter)
249
+ expect(described_class).to receive(:ensure_spec_opts_have_knapsack_pro_formatters)
228
250
  options = double
229
251
  expect(RSpec::Core::ConfigurationOptions).to receive(:new).with([
230
252
  '--no-color',
@@ -241,8 +263,6 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
241
263
 
242
264
  expect(KnapsackPro::Hooks::Queue).to receive(:call_after_subset_queue)
243
265
 
244
- expect(KnapsackPro::Report).to receive(:save_subset_queue_to_file)
245
-
246
266
  configuration = double
247
267
  expect(rspec_core_runner).to receive(:configuration).twice.and_return(configuration)
248
268
  expect(configuration).to receive(:seed_used?).and_return(true)
@@ -344,12 +364,7 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
344
364
 
345
365
  expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_SUBSET_QUEUE_ID', subset_queue_id)
346
366
 
347
- tracker = instance_double(KnapsackPro::Tracker)
348
- expect(KnapsackPro).to receive(:tracker).twice.and_return(tracker)
349
- expect(tracker).to receive(:reset!)
350
- expect(tracker).to receive(:set_prerun_tests).with(test_file_paths)
351
-
352
- expect(described_class).to receive(:ensure_spec_opts_have_rspec_queue_summary_formatter)
367
+ expect(described_class).to receive(:ensure_spec_opts_have_knapsack_pro_formatters)
353
368
  options = double
354
369
  expect(RSpec::Core::ConfigurationOptions).to receive(:new).with([
355
370
  '--no-color',
@@ -361,16 +376,14 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
361
376
  expect(RSpec::Core::Runner).to receive(:new).with(options).and_return(rspec_core_runner)
362
377
  expect(rspec_core_runner).to receive(:run).with($stderr, $stdout).and_raise SystemExit
363
378
  expect(KnapsackPro::Hooks::Queue).to receive(:call_before_subset_queue)
364
- allow(KnapsackPro::Report).to receive(:save_subset_queue_to_file)
365
379
  allow(KnapsackPro::Hooks::Queue).to receive(:call_after_subset_queue)
366
380
  allow(KnapsackPro::Hooks::Queue).to receive(:call_after_queue)
367
381
  allow(KnapsackPro::Formatters::RSpecQueueSummaryFormatter).to receive(:print_exit_summary)
368
382
  expect(Kernel).to receive(:exit).with(1)
369
383
  end
370
384
 
371
- it 'does not call #save_subset_queue_to_file or #rspec_clear_examples' do
385
+ it 'does not call #rspec_clear_examples' do
372
386
  expect(described_class).not_to receive(:rspec_clear_examples)
373
- expect(KnapsackPro::Report).not_to receive(:save_subset_queue_to_file)
374
387
  expect { subject }.to raise_error SystemExit
375
388
  end
376
389
 
@@ -411,7 +424,14 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
411
424
  expect(KnapsackPro::Formatters::RSpecQueueProfileFormatterExtension).to receive(:print_summary)
412
425
 
413
426
  expect(KnapsackPro::Hooks::Queue).to receive(:call_after_queue)
414
- expect(KnapsackPro::Report).to receive(:save_node_queue_to_api)
427
+
428
+ time_tracker = instance_double(KnapsackPro::Formatters::TimeTracker)
429
+ times = all_test_file_paths.map do |path|
430
+ [{ path: path, time_execution: 1.0 }]
431
+ end
432
+ expect(time_tracker).to receive(:queue).and_return(times)
433
+ expect(KnapsackPro::Formatters::TimeTrackerFetcher).to receive(:call).and_return(time_tracker)
434
+ expect(KnapsackPro::Report).to receive(:save_node_queue_to_api).with(times)
415
435
 
416
436
  expect(logger).to receive(:info)
417
437
  .with('To retry all the tests assigned to this CI node, please run the following command on your machine:')
@@ -448,7 +468,15 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
448
468
 
449
469
  it do
450
470
  expect(KnapsackPro::Hooks::Queue).to receive(:call_after_queue)
451
- expect(KnapsackPro::Report).to receive(:save_node_queue_to_api)
471
+
472
+ time_tracker = instance_double(KnapsackPro::Formatters::TimeTracker)
473
+ times = all_test_file_paths.map do |path|
474
+ [{ path: path, time_execution: 0.0 }]
475
+ end
476
+ expect(time_tracker).to receive(:queue).and_return(times)
477
+ expect(KnapsackPro::Formatters::TimeTrackerFetcher).to receive(:call).and_return(time_tracker)
478
+ expect(KnapsackPro::Report).to receive(:save_node_queue_to_api).with(times)
479
+
452
480
  expect(KnapsackPro).to_not receive(:logger)
453
481
 
454
482
  expect(subject).to eq({
@@ -460,29 +488,40 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
460
488
  end
461
489
  end
462
490
 
463
- describe '.ensure_spec_opts_have_rspec_queue_summary_formatter' do
464
- subject { described_class.ensure_spec_opts_have_rspec_queue_summary_formatter }
491
+ describe '.ensure_spec_opts_have_knapsack_pro_formatters' do
492
+ subject { described_class.ensure_spec_opts_have_knapsack_pro_formatters }
465
493
 
466
494
  context 'when `SPEC_OPTS` is set' do
467
- context 'when `SPEC_OPTS` has RSpec Queue Summary Formatter' do
495
+ context 'when `SPEC_OPTS` has RSpecQueueSummaryFormatter' do
468
496
  before do
469
497
  stub_const('ENV', { 'SPEC_OPTS' => '--format json --format KnapsackPro::Formatters::RSpecQueueSummaryFormatter' })
470
498
  end
471
499
 
472
- it 'does nothing' do
500
+ it 'adds TimeTracker' do
501
+ subject
502
+ expect(ENV['SPEC_OPTS']).to eq '--format json --format KnapsackPro::Formatters::RSpecQueueSummaryFormatter --format KnapsackPro::Formatters::TimeTracker'
503
+ end
504
+ end
505
+
506
+ context 'when `SPEC_OPTS` has TimeTracker' do
507
+ before do
508
+ stub_const('ENV', { 'SPEC_OPTS' => '--format json --format KnapsackPro::Formatters::TimeTracker' })
509
+ end
510
+
511
+ it 'adds RSpecQueueSummaryFormatter' do
473
512
  subject
474
- expect(ENV['SPEC_OPTS']).to eq '--format json --format KnapsackPro::Formatters::RSpecQueueSummaryFormatter'
513
+ expect(ENV['SPEC_OPTS']).to eq '--format json --format KnapsackPro::Formatters::TimeTracker --format KnapsackPro::Formatters::RSpecQueueSummaryFormatter'
475
514
  end
476
515
  end
477
516
 
478
- context 'when `SPEC_OPTS` has no RSpec Queue Summary Formatter' do
517
+ context 'when `SPEC_OPTS` has no Knapsack Pro formatters' do
479
518
  before do
480
519
  stub_const('ENV', { 'SPEC_OPTS' => '--format json' })
481
520
  end
482
521
 
483
- it 'adds RSpec Queue Summary Formatter to `SPEC_OPTS`' do
522
+ it 'adds RSpecQueueSummaryFormatter and TimeTracker to `SPEC_OPTS`' do
484
523
  subject
485
- expect(ENV['SPEC_OPTS']).to eq '--format json --format KnapsackPro::Formatters::RSpecQueueSummaryFormatter'
524
+ expect(ENV['SPEC_OPTS']).to eq '--format json --format KnapsackPro::Formatters::RSpecQueueSummaryFormatter --format KnapsackPro::Formatters::TimeTracker'
486
525
  end
487
526
  end
488
527
  end
@@ -42,14 +42,11 @@ describe KnapsackPro::Runners::RSpecRunner do
42
42
  expect(KnapsackPro::Adapters::RSpecAdapter).to receive(:verify_bind_method_called).ordered
43
43
  expect(KnapsackPro::Adapters::RSpecAdapter).to receive(:ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!).with(['--profile', '--color']).ordered
44
44
 
45
- tracker = instance_double(KnapsackPro::Tracker)
46
- expect(KnapsackPro).to receive(:tracker).and_return(tracker)
47
- expect(tracker).to receive(:set_prerun_tests).with(test_file_paths)
48
-
49
45
  expect(Rake::Task).to receive(:[]).with('knapsack_pro:rspec_run').at_least(1).and_return(task)
50
46
 
51
47
  expect(RSpec::Core::RakeTask).to receive(:new).with('knapsack_pro:rspec_run').and_yield(task_config)
52
- expect(task_config).to receive(:rspec_opts=).with('--profile --color --default-path fake-test-dir spec/a_spec.rb spec/b_spec.rb[1:1]')
48
+ expect(RSpec::Core::ConfigurationOptions).to receive_message_chain(:new, :options).and_return({})
49
+ expect(task_config).to receive(:rspec_opts=).with('--profile --color --format progress --format KnapsackPro::Formatters::TimeTracker --default-path fake-test-dir spec/a_spec.rb spec/b_spec.rb[1:1]')
53
50
  expect(task_config).to receive(:pattern=).with([])
54
51
  end
55
52