knapsack_pro 5.3.4 → 5.3.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6952ceb372cbcc2dc8c2c5514f0fe68bc4be51572199168e3d7f7992eabdfe43
4
- data.tar.gz: '077863b80cab5c090ad84c62cbb0c2d680757ea19da59e94c92cb9ee2770ba90'
3
+ metadata.gz: 202eb37b7550c8556fadd902ed204ea71d5c928b2ed79f3452aa2f7dabee1a35
4
+ data.tar.gz: 846ec0dd9f9953bbbfeed2b9f77535a25e5182de8b3798dcff88a48fce1ba0f9
5
5
  SHA512:
6
- metadata.gz: 3ba6a868b796019d571c077131e1cd33016bee27e7a8cbd1b1d35cfe31532c2049734d1cf24686ac5ef63a881a82ed0c3d811d4e04ccf17ba0444a856121e363
7
- data.tar.gz: a717af5c831cfd8984ac2c2d691b557dd7cd919e1e7a223d9347eac8d28345700bdcefdf50d0fc5ab10a23c2c9dd4811e95198c443530d83006e7baeee898dbb
6
+ metadata.gz: 6e9e1bffd253bade681efd59cdb43a13c8ae99bb43981dbf8aaea0f7adc3e5d2cce530488e6308a7eb35821abfc9245f26236e3e3dc323b68dbd3fd457905865
7
+ data.tar.gz: aedf904bdf8f765e1fdcbe651ee9d1f839201c48fdad7750668c88cb2f70bb1f61fff1fa633062f0be3bf31770656d48b0467b61b970f6d03526c430b7dc12c8
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ### 5.3.5
4
+
5
+ * Handle RSpec exceptions when running RSpec in Queue Mode
6
+
7
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/214
8
+
9
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/215
10
+
11
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v5.3.4...v5.3.5
12
+
3
13
  ### 5.3.4
4
14
 
5
15
  * fix(Queue Mode): handle OS signals and RSpec internal `wants_to_quit` and `rspec_is_quitting` states to stop consuming tests from the Queue API when the CI node is terminated
@@ -62,11 +62,39 @@ module KnapsackPro
62
62
  unless most_recent_pending.empty?
63
63
  registered_output.puts('All pending tests on this CI node:')
64
64
  registered_output.puts(most_recent_pending)
65
+ registered_output.puts('')
65
66
  end
66
67
 
67
68
  unless most_recent_failures_summary.empty?
68
69
  registered_output.puts('All failed tests on this CI node:')
69
70
  registered_output.puts(most_recent_failures_summary)
71
+ registered_output.puts('')
72
+ end
73
+
74
+ registered_output.puts(most_recent_summary)
75
+ end
76
+
77
+ def self.print_exit_summary
78
+ registered_output.puts('Knapsack Pro Queue exited/aborted!')
79
+ registered_output.puts('')
80
+
81
+ unexecuted_test_files = KnapsackPro.tracker.unexecuted_test_files
82
+ unless unexecuted_test_files.empty?
83
+ registered_output.puts('Unexecuted tests on this CI node:')
84
+ registered_output.puts(unexecuted_test_files)
85
+ registered_output.puts('')
86
+ end
87
+
88
+ unless most_recent_pending.empty?
89
+ registered_output.puts('All pending tests on this CI node:')
90
+ registered_output.puts(most_recent_pending)
91
+ registered_output.puts('')
92
+ end
93
+
94
+ unless most_recent_failures_summary.empty?
95
+ registered_output.puts('All failed tests on this CI node:')
96
+ registered_output.puts(most_recent_failures_summary)
97
+ registered_output.puts('')
70
98
  end
71
99
 
72
100
  registered_output.puts(most_recent_summary)
@@ -92,35 +92,44 @@ module KnapsackPro
92
92
  options = ::RSpec::Core::ConfigurationOptions.new(cli_args)
93
93
  rspec_runner = ::RSpec::Core::Runner.new(options)
94
94
 
95
- exit_code = rspec_runner.run($stderr, $stdout)
96
- exitstatus = exit_code if exit_code != 0
97
-
98
- if rspec_runner.world.wants_to_quit
99
- KnapsackPro.logger.warn('RSpec wants to quit.')
100
- set_terminate_process
101
- end
102
- if rspec_runner.world.rspec_is_quitting
103
- KnapsackPro.logger.warn('RSpec is quitting.')
104
- set_terminate_process
95
+ begin
96
+ exit_code = rspec_runner.run($stderr, $stdout)
97
+ exitstatus = exit_code if exit_code != 0
98
+ rescue Exception => exception
99
+ KnapsackPro.logger.error("Having exception when running RSpec: #{exception.inspect}")
100
+ KnapsackPro::Formatters::RSpecQueueSummaryFormatter.print_exit_summary
101
+ KnapsackPro::Hooks::Queue.call_after_subset_queue
102
+ KnapsackPro::Hooks::Queue.call_after_queue
103
+ Kernel.exit(1)
104
+ raise
105
+ else
106
+ if rspec_runner.world.wants_to_quit
107
+ KnapsackPro.logger.warn('RSpec wants to quit.')
108
+ set_terminate_process
109
+ end
110
+ if rspec_runner.world.rspec_is_quitting
111
+ KnapsackPro.logger.warn('RSpec is quitting.')
112
+ set_terminate_process
113
+ end
114
+
115
+ printable_args = args_with_seed_option_added_when_viable(args, rspec_runner)
116
+ log_rspec_command(printable_args, test_file_paths, :subset_queue)
117
+
118
+ rspec_clear_examples
119
+
120
+ KnapsackPro::Hooks::Queue.call_after_subset_queue
121
+
122
+ KnapsackPro::Report.save_subset_queue_to_file
123
+
124
+ return {
125
+ status: :next,
126
+ runner: runner,
127
+ can_initialize_queue: false,
128
+ args: args,
129
+ exitstatus: exitstatus,
130
+ all_test_file_paths: all_test_file_paths,
131
+ }
105
132
  end
106
-
107
- printable_args = args_with_seed_option_added_when_viable(args, rspec_runner)
108
- log_rspec_command(printable_args, test_file_paths, :subset_queue)
109
-
110
- rspec_clear_examples
111
-
112
- KnapsackPro::Hooks::Queue.call_after_subset_queue
113
-
114
- KnapsackPro::Report.save_subset_queue_to_file
115
-
116
- return {
117
- status: :next,
118
- runner: runner,
119
- can_initialize_queue: false,
120
- args: args,
121
- exitstatus: exitstatus,
122
- all_test_file_paths: all_test_file_paths,
123
- }
124
133
  end
125
134
  end
126
135
 
@@ -68,6 +68,12 @@ module KnapsackPro
68
68
  @prerun_tests_loaded = true
69
69
  end
70
70
 
71
+ def unexecuted_test_files
72
+ @test_files_with_time.map do |path, hash|
73
+ path unless hash[:measured_time]
74
+ end.compact
75
+ end
76
+
71
77
  def to_a
72
78
  # When the test files are not loaded in the memory then load them from the disk.
73
79
  # Useful for the Regular Mode when the memory is not shared between tracker instances.
@@ -1,3 +1,3 @@
1
1
  module KnapsackPro
2
- VERSION = '5.3.4'
2
+ VERSION = '5.3.5'
3
3
  end
@@ -212,126 +212,183 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
212
212
  double(world: double(wants_to_quit: rspec_wants_to_quit, rspec_is_quitting: rspec_is_quitting))
213
213
  end
214
214
 
215
- before do
216
- subset_queue_id = 'fake-subset-queue-id'
217
- expect(KnapsackPro::Config::EnvGenerator).to receive(:set_subset_queue_id).and_return(subset_queue_id)
215
+ context 'having no exception when running RSpec' do
216
+ before do
217
+ subset_queue_id = 'fake-subset-queue-id'
218
+ expect(KnapsackPro::Config::EnvGenerator).to receive(:set_subset_queue_id).and_return(subset_queue_id)
218
219
 
219
- expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_SUBSET_QUEUE_ID', subset_queue_id)
220
+ expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_SUBSET_QUEUE_ID', subset_queue_id)
220
221
 
221
- tracker = instance_double(KnapsackPro::Tracker)
222
- expect(KnapsackPro).to receive(:tracker).twice.and_return(tracker)
223
- expect(tracker).to receive(:reset!)
224
- expect(tracker).to receive(:set_prerun_tests).with(test_file_paths)
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)
225
226
 
226
- expect(described_class).to receive(:ensure_spec_opts_have_rspec_queue_summary_formatter)
227
- options = double
228
- expect(RSpec::Core::ConfigurationOptions).to receive(:new).with([
229
- '--no-color',
230
- '--default-path', 'fake-test-dir',
231
- 'a_spec.rb', 'b_spec.rb',
232
- ]).and_return(options)
227
+ expect(described_class).to receive(:ensure_spec_opts_have_rspec_queue_summary_formatter)
228
+ options = double
229
+ expect(RSpec::Core::ConfigurationOptions).to receive(:new).with([
230
+ '--no-color',
231
+ '--default-path', 'fake-test-dir',
232
+ 'a_spec.rb', 'b_spec.rb',
233
+ ]).and_return(options)
233
234
 
234
- expect(RSpec::Core::Runner).to receive(:new).with(options).and_return(rspec_core_runner)
235
- expect(rspec_core_runner).to receive(:run).with($stderr, $stdout).and_return(exit_code)
235
+ expect(RSpec::Core::Runner).to receive(:new).with(options).and_return(rspec_core_runner)
236
+ expect(rspec_core_runner).to receive(:run).with($stderr, $stdout).and_return(exit_code)
236
237
 
237
- expect(described_class).to receive(:rspec_clear_examples)
238
+ expect(described_class).to receive(:rspec_clear_examples)
238
239
 
239
- expect(KnapsackPro::Hooks::Queue).to receive(:call_before_subset_queue)
240
+ expect(KnapsackPro::Hooks::Queue).to receive(:call_before_subset_queue)
240
241
 
241
- expect(KnapsackPro::Hooks::Queue).to receive(:call_after_subset_queue)
242
+ expect(KnapsackPro::Hooks::Queue).to receive(:call_after_subset_queue)
242
243
 
243
- expect(KnapsackPro::Report).to receive(:save_subset_queue_to_file)
244
+ expect(KnapsackPro::Report).to receive(:save_subset_queue_to_file)
244
245
 
245
- configuration = double
246
- expect(rspec_core_runner).to receive(:configuration).twice.and_return(configuration)
247
- expect(configuration).to receive(:seed_used?).and_return(true)
248
- expect(configuration).to receive(:seed).and_return(rspec_seed)
246
+ configuration = double
247
+ expect(rspec_core_runner).to receive(:configuration).twice.and_return(configuration)
248
+ expect(configuration).to receive(:seed_used?).and_return(true)
249
+ expect(configuration).to receive(:seed).and_return(rspec_seed)
249
250
 
250
- expect(KnapsackPro).to receive(:logger).at_least(2).and_return(logger)
251
- expect(logger).to receive(:info)
252
- .with("To retry the last batch of tests fetched from the API Queue, please run the following command on your machine:")
253
- expect(logger).to receive(:info).with(/#{args.join(' ')} --seed #{rspec_seed}/)
254
- end
251
+ expect(KnapsackPro).to receive(:logger).at_least(2).and_return(logger)
252
+ expect(logger).to receive(:info)
253
+ .with("To retry the last batch of tests fetched from the API Queue, please run the following command on your machine:")
254
+ expect(logger).to receive(:info).with(/#{args.join(' ')} --seed #{rspec_seed}/)
255
+ end
255
256
 
256
- context 'when the exit code is zero' do
257
- let(:exit_code) { 0 }
257
+ context 'when the exit code is zero' do
258
+ let(:exit_code) { 0 }
258
259
 
259
- it do
260
- expect(subject).to eq({
261
- status: :next,
262
- runner: runner,
263
- can_initialize_queue: false,
264
- args: args,
265
- exitstatus: exitstatus,
266
- all_test_file_paths: test_file_paths,
267
- })
260
+ it do
261
+ expect(subject).to eq({
262
+ status: :next,
263
+ runner: runner,
264
+ can_initialize_queue: false,
265
+ args: args,
266
+ exitstatus: exitstatus,
267
+ all_test_file_paths: test_file_paths,
268
+ })
269
+ end
268
270
  end
269
- end
270
271
 
271
- context 'when the exit code is not zero' do
272
- let(:exit_code) { double }
272
+ context 'when the exit code is not zero' do
273
+ let(:exit_code) { double }
273
274
 
274
- it do
275
- expect(subject).to eq({
276
- status: :next,
277
- runner: runner,
278
- can_initialize_queue: false,
279
- args: args,
280
- exitstatus: exit_code,
281
- all_test_file_paths: test_file_paths,
282
- })
275
+ it do
276
+ expect(subject).to eq({
277
+ status: :next,
278
+ runner: runner,
279
+ can_initialize_queue: false,
280
+ args: args,
281
+ exitstatus: exit_code,
282
+ all_test_file_paths: test_file_paths,
283
+ })
284
+ end
283
285
  end
284
- end
285
286
 
286
- context 'when RSpec wants to quit' do
287
- let(:exit_code) { 0 }
288
- let(:rspec_wants_to_quit) { true }
287
+ context 'when RSpec wants to quit' do
288
+ let(:exit_code) { 0 }
289
+ let(:rspec_wants_to_quit) { true }
290
+
291
+ after do
292
+ described_class.class_variable_set(:@@terminate_process, false)
293
+ end
294
+
295
+ it 'terminates the process' do
296
+ expect(logger).to receive(:warn).with('RSpec wants to quit.')
289
297
 
290
- after do
291
- described_class.class_variable_set(:@@terminate_process, false)
298
+ expect(described_class.class_variable_get(:@@terminate_process)).to be false
299
+
300
+ expect(subject).to eq({
301
+ status: :next,
302
+ runner: runner,
303
+ can_initialize_queue: false,
304
+ args: args,
305
+ exitstatus: exitstatus,
306
+ all_test_file_paths: test_file_paths,
307
+ })
308
+
309
+ expect(described_class.class_variable_get(:@@terminate_process)).to be true
310
+ end
292
311
  end
293
312
 
294
- it 'terminates the process' do
295
- expect(logger).to receive(:warn).with('RSpec wants to quit.')
313
+ context 'when RSpec is quitting' do
314
+ let(:exit_code) { 0 }
315
+ let(:rspec_is_quitting) { true }
296
316
 
297
- expect(described_class.class_variable_get(:@@terminate_process)).to be false
317
+ after do
318
+ described_class.class_variable_set(:@@terminate_process, false)
319
+ end
298
320
 
299
- expect(subject).to eq({
300
- status: :next,
301
- runner: runner,
302
- can_initialize_queue: false,
303
- args: args,
304
- exitstatus: exitstatus,
305
- all_test_file_paths: test_file_paths,
306
- })
321
+ it 'terminates the process' do
322
+ expect(logger).to receive(:warn).with('RSpec is quitting.')
307
323
 
308
- expect(described_class.class_variable_get(:@@terminate_process)).to be true
324
+ expect(described_class.class_variable_get(:@@terminate_process)).to be false
325
+
326
+ expect(subject).to eq({
327
+ status: :next,
328
+ runner: runner,
329
+ can_initialize_queue: false,
330
+ args: args,
331
+ exitstatus: exitstatus,
332
+ all_test_file_paths: test_file_paths,
333
+ })
334
+
335
+ expect(described_class.class_variable_get(:@@terminate_process)).to be true
336
+ end
309
337
  end
310
338
  end
311
339
 
312
- context 'when RSpec is quitting' do
313
- let(:exit_code) { 0 }
314
- let(:rspec_is_quitting) { true }
315
-
316
- after do
317
- described_class.class_variable_set(:@@terminate_process, false)
340
+ context 'having exception when running RSpec' do
341
+ before do
342
+ subset_queue_id = 'fake-subset-queue-id'
343
+ expect(KnapsackPro::Config::EnvGenerator).to receive(:set_subset_queue_id).and_return(subset_queue_id)
344
+
345
+ expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_SUBSET_QUEUE_ID', subset_queue_id)
346
+
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)
353
+ options = double
354
+ expect(RSpec::Core::ConfigurationOptions).to receive(:new).with([
355
+ '--no-color',
356
+ '--default-path', 'fake-test-dir',
357
+ 'a_spec.rb', 'b_spec.rb',
358
+ ]).and_return(options)
359
+
360
+ rspec_core_runner = double
361
+ expect(RSpec::Core::Runner).to receive(:new).with(options).and_return(rspec_core_runner)
362
+ expect(rspec_core_runner).to receive(:run).with($stderr, $stdout).and_raise SystemExit
363
+ expect(KnapsackPro::Hooks::Queue).to receive(:call_before_subset_queue)
364
+ allow(KnapsackPro::Report).to receive(:save_subset_queue_to_file)
365
+ allow(KnapsackPro::Hooks::Queue).to receive(:call_after_subset_queue)
366
+ allow(KnapsackPro::Hooks::Queue).to receive(:call_after_queue)
367
+ allow(KnapsackPro::Formatters::RSpecQueueSummaryFormatter).to receive(:print_exit_summary)
368
+ expect(Kernel).to receive(:exit).with(1)
318
369
  end
319
370
 
320
- it 'terminates the process' do
321
- expect(logger).to receive(:warn).with('RSpec is quitting.')
371
+ it 'does not call #save_subset_queue_to_file or #rspec_clear_examples' do
372
+ expect(described_class).not_to receive(:rspec_clear_examples)
373
+ expect(KnapsackPro::Report).not_to receive(:save_subset_queue_to_file)
374
+ expect { subject }.to raise_error SystemExit
375
+ end
322
376
 
323
- expect(described_class.class_variable_get(:@@terminate_process)).to be false
377
+ it 'logs the exception' do
378
+ expect(KnapsackPro).to receive(:logger).once.and_return(logger)
379
+ expect(logger).to receive(:error).with("Having exception when running RSpec: #<SystemExit: SystemExit>")
380
+ expect { subject }.to raise_error SystemExit
381
+ end
324
382
 
325
- expect(subject).to eq({
326
- status: :next,
327
- runner: runner,
328
- can_initialize_queue: false,
329
- args: args,
330
- exitstatus: exitstatus,
331
- all_test_file_paths: test_file_paths,
332
- })
383
+ it 'calls #print_exit_summary' do
384
+ expect(KnapsackPro::Formatters::RSpecQueueSummaryFormatter).to receive(:print_exit_summary)
385
+ expect { subject }.to raise_error SystemExit
386
+ end
333
387
 
334
- expect(described_class.class_variable_get(:@@terminate_process)).to be true
388
+ it 'calls #call_after_subset_queue and #call_after_queue' do
389
+ expect(KnapsackPro::Hooks::Queue).to receive(:call_after_subset_queue)
390
+ expect(KnapsackPro::Hooks::Queue).to receive(:call_after_queue)
391
+ expect { subject }.to raise_error SystemExit
335
392
  end
336
393
  end
337
394
  end
@@ -185,4 +185,21 @@ describe KnapsackPro::Tracker do
185
185
  expect(tracker.prerun_tests_loaded).to be false
186
186
  end
187
187
  end
188
+
189
+
190
+ describe '#unexecuted_test_files' do
191
+ before do
192
+ tracker.set_prerun_tests(['a_spec.rb', 'b_spec.rb', 'c_spec.rb'])
193
+
194
+ # measure execution time for b_spec.rb
195
+ tracker.current_test_path = 'b_spec.rb'
196
+ tracker.start_timer
197
+ sleep 0.1
198
+ tracker.stop_timer
199
+ end
200
+
201
+ it 'returns test files without measured time' do
202
+ expect(tracker.unexecuted_test_files).to eq(['a_spec.rb', 'c_spec.rb'])
203
+ end
204
+ end
188
205
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knapsack_pro
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.3.4
4
+ version: 5.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - ArturT
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-26 00:00:00.000000000 Z
11
+ date: 2023-08-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake