knapsack_pro 9.0.0 → 9.1.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.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/lib/knapsack_pro/adapters/minitest_adapter.rb +8 -13
  3. data/lib/knapsack_pro/client/connection.rb +1 -1
  4. data/lib/knapsack_pro/config/env.rb +1 -24
  5. data/lib/knapsack_pro/version.rb +1 -1
  6. metadata +2 -196
  7. data/.circleci/config.yml +0 -468
  8. data/.github/assets/install-button.png +0 -0
  9. data/.github/assets/knapsack-diamonds.png +0 -0
  10. data/.github/dependabot.yml +0 -11
  11. data/.github/pull_request_template.md +0 -11
  12. data/.gitignore +0 -39
  13. data/.rspec +0 -5
  14. data/CHANGELOG.md +0 -1995
  15. data/Gemfile +0 -13
  16. data/LICENSE +0 -22
  17. data/README.md +0 -90
  18. data/Rakefile +0 -2
  19. data/knapsack_pro.gemspec +0 -43
  20. data/spec/fixtures/test_file_list_source_file.txt +0 -6
  21. data/spec/fixtures/vcr_cassettes/api/v1/build_distributions/subset/invalid_test_suite_token.yml +0 -59
  22. data/spec/fixtures/vcr_cassettes/api/v1/build_distributions/subset/success.yml +0 -61
  23. data/spec/fixtures/vcr_cassettes/api/v1/build_subsets/create/invalid_test_suite_token.yml +0 -50
  24. data/spec/fixtures/vcr_cassettes/api/v1/build_subsets/create/success.yml +0 -50
  25. data/spec/integration/api/build_distributions_subset_spec.rb +0 -77
  26. data/spec/integration/api/build_subsets_create_spec.rb +0 -77
  27. data/spec/integration/runners/fallback_spec.rb +0 -131
  28. data/spec/integration/runners/queue/cucumber_runner_fallback_spec.rb +0 -129
  29. data/spec/integration/runners/queue/minitest_runner_fallback_spec.rb +0 -129
  30. data/spec/integration/runners/queue/rspec_runner.rb +0 -80
  31. data/spec/integration/runners/queue/rspec_runner_fallback_spec.rb +0 -137
  32. data/spec/integration/runners/queue/rspec_runner_spec.rb +0 -2672
  33. data/spec/knapsack_pro/adapters/base_adapter_spec.rb +0 -221
  34. data/spec/knapsack_pro/adapters/cucumber_adapter_spec.rb +0 -216
  35. data/spec/knapsack_pro/adapters/minitest_adapter_spec.rb +0 -189
  36. data/spec/knapsack_pro/adapters/rspec_adapter_spec.rb +0 -427
  37. data/spec/knapsack_pro/adapters/spinach_adapter_spec.rb +0 -61
  38. data/spec/knapsack_pro/adapters/test_unit_adapter_spec.rb +0 -86
  39. data/spec/knapsack_pro/base_allocator_builder_spec.rb +0 -102
  40. data/spec/knapsack_pro/build_distribution_fetcher_spec.rb +0 -89
  41. data/spec/knapsack_pro/client/api/action_spec.rb +0 -17
  42. data/spec/knapsack_pro/client/api/v1/base_spec.rb +0 -2
  43. data/spec/knapsack_pro/client/api/v1/build_distributions_spec.rb +0 -95
  44. data/spec/knapsack_pro/client/api/v1/build_subsets_spec.rb +0 -35
  45. data/spec/knapsack_pro/client/api/v1/queues_spec.rb +0 -83
  46. data/spec/knapsack_pro/client/connection_spec.rb +0 -581
  47. data/spec/knapsack_pro/config/ci/app_veyor_spec.rb +0 -87
  48. data/spec/knapsack_pro/config/ci/base_spec.rb +0 -10
  49. data/spec/knapsack_pro/config/ci/buildkite_spec.rb +0 -135
  50. data/spec/knapsack_pro/config/ci/circle_spec.rb +0 -122
  51. data/spec/knapsack_pro/config/ci/cirrus_ci_spec.rb +0 -87
  52. data/spec/knapsack_pro/config/ci/codefresh_spec.rb +0 -81
  53. data/spec/knapsack_pro/config/ci/codeship_spec.rb +0 -80
  54. data/spec/knapsack_pro/config/ci/github_actions_spec.rb +0 -140
  55. data/spec/knapsack_pro/config/ci/gitlab_ci_spec.rb +0 -137
  56. data/spec/knapsack_pro/config/ci/heroku_spec.rb +0 -87
  57. data/spec/knapsack_pro/config/ci/semaphore2_spec.rb +0 -133
  58. data/spec/knapsack_pro/config/ci/semaphore_spec.rb +0 -87
  59. data/spec/knapsack_pro/config/ci/travis_spec.rb +0 -73
  60. data/spec/knapsack_pro/config/env_generator_spec.rb +0 -52
  61. data/spec/knapsack_pro/config/env_spec.rb +0 -1291
  62. data/spec/knapsack_pro/config/temp_files_spec.rb +0 -25
  63. data/spec/knapsack_pro/crypto/branch_encryptor_spec.rb +0 -53
  64. data/spec/knapsack_pro/crypto/decryptor_spec.rb +0 -83
  65. data/spec/knapsack_pro/crypto/digestor_spec.rb +0 -13
  66. data/spec/knapsack_pro/crypto/encryptor_spec.rb +0 -58
  67. data/spec/knapsack_pro/formatters/time_tracker_fetcher_spec.rb +0 -27
  68. data/spec/knapsack_pro/formatters/time_tracker_spec.rb +0 -448
  69. data/spec/knapsack_pro/hooks/queue_spec.rb +0 -199
  70. data/spec/knapsack_pro/presenter_spec.rb +0 -57
  71. data/spec/knapsack_pro/pure/queue/rspec_pure_spec.rb +0 -248
  72. data/spec/knapsack_pro/queue_spec.rb +0 -35
  73. data/spec/knapsack_pro/report_spec.rb +0 -232
  74. data/spec/knapsack_pro/repository_adapter_initiator_spec.rb +0 -21
  75. data/spec/knapsack_pro/repository_adapters/base_adapter_spec.rb +0 -13
  76. data/spec/knapsack_pro/repository_adapters/env_adapter_spec.rb +0 -27
  77. data/spec/knapsack_pro/repository_adapters/git_adapter_spec.rb +0 -106
  78. data/spec/knapsack_pro/runners/base_runner_spec.rb +0 -87
  79. data/spec/knapsack_pro/runners/cucumber_runner_spec.rb +0 -92
  80. data/spec/knapsack_pro/runners/minitest_runner_spec.rb +0 -57
  81. data/spec/knapsack_pro/runners/queue/base_runner_spec.rb +0 -73
  82. data/spec/knapsack_pro/runners/queue/cucumber_runner_spec.rb +0 -209
  83. data/spec/knapsack_pro/runners/queue/minitest_runner_spec.rb +0 -203
  84. data/spec/knapsack_pro/runners/rspec_runner_spec.rb +0 -111
  85. data/spec/knapsack_pro/runners/spinach_runner_spec.rb +0 -56
  86. data/spec/knapsack_pro/runners/test_unit_runner_spec.rb +0 -62
  87. data/spec/knapsack_pro/slow_test_file_determiner_spec.rb +0 -119
  88. data/spec/knapsack_pro/slow_test_file_finder_spec.rb +0 -42
  89. data/spec/knapsack_pro/task_loader_spec.rb +0 -14
  90. data/spec/knapsack_pro/test_case_detectors/rspec_test_example_detector_spec.rb +0 -217
  91. data/spec/knapsack_pro/test_case_mergers/base_merger_spec.rb +0 -27
  92. data/spec/knapsack_pro/test_case_mergers/rspec_merger_spec.rb +0 -81
  93. data/spec/knapsack_pro/test_file_cleaner_spec.rb +0 -11
  94. data/spec/knapsack_pro/test_file_finder_spec.rb +0 -176
  95. data/spec/knapsack_pro/test_file_pattern_spec.rb +0 -49
  96. data/spec/knapsack_pro/test_file_presenter_spec.rb +0 -22
  97. data/spec/knapsack_pro/test_files_with_test_cases_composer_spec.rb +0 -41
  98. data/spec/knapsack_pro/test_flat_distributor_spec.rb +0 -60
  99. data/spec/knapsack_pro/tracker_spec.rb +0 -184
  100. data/spec/knapsack_pro/utils_spec.rb +0 -55
  101. data/spec/knapsack_pro_spec.rb +0 -116
  102. data/spec/spec_helper.rb +0 -47
  103. data/spec/support/.gitkeep +0 -0
  104. data/spec/support/fakes/cucumber.rb +0 -25
  105. data/spec/support/fakes/minitest.rb +0 -18
  106. data/spec/support/shared_examples/adapter.rb +0 -17
  107. data/spec_fake/controllers/users_controller_spec.rb +0 -0
  108. data/spec_fake/models/admin_spec.rb +0 -0
  109. data/spec_fake/models/user_spec.rb +0 -0
  110. data/spec_fake/spec_helper.rb +0 -0
  111. data/spec_time_tracker/spec_helper.rb +0 -29
  112. data/test_fake/a_test.rb +0 -0
  113. data/test_fake/b_test.rb +0 -0
@@ -1,2672 +0,0 @@
1
- require 'open3'
2
- require 'json'
3
- require 'nokogiri'
4
- require 'ostruct'
5
-
6
- describe "#{KnapsackPro::Runners::Queue::RSpecRunner} - Integration tests", :clear_tmp do
7
- SPEC_DIRECTORY = 'spec_integration'
8
-
9
- class Spec
10
- attr_reader :path, :content
11
-
12
- def initialize(path, content)
13
- @path = "#{SPEC_DIRECTORY}/#{path}"
14
- @content = content
15
- end
16
- end
17
-
18
- # @param rspec_options String
19
- # @param spec_batches Array[Array[String]]
20
- def generate_specs(spec_helper, rspec_options, spec_batches)
21
- ENV['TEST__RSPEC_OPTIONS'] = rspec_options
22
- generate_spec_helper(spec_helper)
23
- paths = generate_spec_files(spec_batches.flatten)
24
- stub_spec_batches(
25
- spec_batches.map { _1.map(&:path) }
26
- )
27
- end
28
-
29
- def generate_spec_helper(spec_helper)
30
- spec_helper_path = "#{SPEC_DIRECTORY}/spec_helper.rb"
31
- File.open(spec_helper_path, 'w') { |file| file.write(spec_helper) }
32
- end
33
-
34
- def generate_spec_files(specs)
35
- specs.map do |spec_item|
36
- File.open(spec_item.path, 'w') { |file| file.write(spec_item.content) }
37
- spec_item.path
38
- end
39
- end
40
-
41
- def create_rails_helper_file(rails_helper)
42
- rails_helper_path = "#{SPEC_DIRECTORY}/rails_helper.rb"
43
- File.open(rails_helper_path, 'w') { |file| file.write(rails_helper) }
44
- end
45
-
46
- def stub_spec_batches(batched_tests)
47
- ENV['TEST__SPEC_BATCHES'] = batched_tests.to_json
48
- end
49
-
50
- # @param test_file_paths Array[String]
51
- # Example: ['spec_integration/a_spec.rb[1:1]']
52
- def stub_test_cases_for_slow_test_files(test_file_paths)
53
- ENV['TEST__TEST_FILE_CASES_FOR_SLOW_TEST_FILES'] = test_file_paths.to_json
54
- end
55
-
56
- def log(stdout, stderr, status)
57
- puts '='*50
58
- puts 'STDOUT:'
59
- puts stdout
60
- puts
61
-
62
- puts '='*50
63
- puts 'STDERR:'
64
- puts stderr
65
- puts
66
-
67
- puts '='*50
68
- puts 'Exit status code:'
69
- puts status
70
- puts
71
- end
72
-
73
- let(:spec_helper_with_knapsack) do
74
- <<~SPEC
75
- require 'knapsack_pro'
76
- KnapsackPro::Adapters::RSpecAdapter.bind
77
- SPEC
78
- end
79
-
80
- let(:command) { 'ruby spec/integration/runners/queue/rspec_runner.rb' }
81
-
82
- subject do
83
- stdout, stderr, status = Open3.capture3(command)
84
- log(stdout, stderr, status) if ENV['TEST__SHOW_DEBUG_LOG'] == 'true'
85
- OpenStruct.new(stdout: stdout, stderr: stderr, exit_code: status.exitstatus)
86
- end
87
-
88
- before do
89
- FileUtils.mkdir_p(SPEC_DIRECTORY)
90
-
91
- ENV['KNAPSACK_PRO_LOG_LEVEL'] = 'debug'
92
- # Useful when creating or editing a test:
93
- # ENV['TEST__SHOW_DEBUG_LOG'] = 'true'
94
- end
95
- after do
96
- FileUtils.rm_rf(SPEC_DIRECTORY)
97
- FileUtils.mkdir_p(SPEC_DIRECTORY)
98
-
99
- ENV.delete('KNAPSACK_PRO_LOG_LEVEL')
100
- ENV.keys.select { _1.start_with?('TEST__') }.each do |key|
101
- ENV.delete(key)
102
- end
103
- end
104
-
105
- context 'when a few batches of tests returned by the Queue API' do
106
- it 'runs tests' do
107
- rspec_options = '--format d'
108
-
109
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
110
- describe 'A_describe' do
111
- it 'A1 test example' do
112
- expect(1).to eq 1
113
- end
114
- end
115
- SPEC
116
-
117
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
118
- describe 'B_describe' do
119
- it 'B1 test example' do
120
- expect(1).to eq 1
121
- end
122
- end
123
- SPEC
124
-
125
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
126
- describe 'C_describe' do
127
- it 'C1 test example' do
128
- expect(1).to eq 1
129
- end
130
- end
131
- SPEC
132
-
133
- generate_specs(spec_helper_with_knapsack, rspec_options, [
134
- [spec_a, spec_b],
135
- [spec_c],
136
- ])
137
-
138
- actual = subject
139
-
140
- expect(actual.stdout).to include('DEBUG -- knapsack_pro: Queue Mode enabled.')
141
-
142
- expect(actual.stdout).to include('A1 test example')
143
- expect(actual.stdout).to include('B1 test example')
144
- expect(actual.stdout).to include('C1 test example')
145
-
146
- expect(actual.stdout).to include('INFO -- knapsack_pro: To retry the last batch of tests fetched from the Queue API, please run the following command on your machine:')
147
- expect(actual.stdout).to include('INFO -- knapsack_pro: bundle exec rspec --format d --default-path spec_integration "spec_integration/a_spec.rb" "spec_integration/b_spec.rb"')
148
- expect(actual.stdout).to include('INFO -- knapsack_pro: bundle exec rspec --format d --default-path spec_integration "spec_integration/c_spec.rb"')
149
-
150
- expect(actual.stdout).to include('INFO -- knapsack_pro: To retry all the tests assigned to this CI node, please run the following command on your machine:')
151
- expect(actual.stdout).to include('INFO -- knapsack_pro: bundle exec rspec --format d --default-path spec_integration "spec_integration/a_spec.rb" "spec_integration/b_spec.rb" "spec_integration/c_spec.rb"')
152
-
153
- expect(actual.stdout).to include('3 examples, 0 failures')
154
-
155
- expect(actual.stdout).to include('DEBUG -- knapsack_pro: Global test execution duration:')
156
-
157
- expect(actual.exit_code).to eq 0
158
- end
159
-
160
- it 'detects test execution times correctly before sending it to API' do
161
- ENV['TEST__LOG_EXECUTION_TIMES'] = 'true'
162
-
163
- rspec_options = '--format d'
164
-
165
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
166
- describe 'A_describe' do
167
- it 'A1 test example' do
168
- expect(1).to eq 1
169
- end
170
- end
171
- SPEC
172
-
173
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
174
- describe 'B_describe' do
175
- it 'B1 test example' do
176
- expect(1).to eq 1
177
- end
178
- end
179
- SPEC
180
-
181
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
182
- describe 'C_describe' do
183
- it 'C1 test example' do
184
- expect(1).to eq 1
185
- end
186
- end
187
- SPEC
188
-
189
- generate_specs(spec_helper_with_knapsack, rspec_options, [
190
- [spec_a, spec_b],
191
- [spec_c],
192
- ])
193
-
194
- actual = subject
195
-
196
- expect(actual.stdout).to include('[INTEGRATION TEST] test_files: 3, test files have execution time: true')
197
-
198
- expect(actual.exit_code).to eq 0
199
- end
200
- end
201
-
202
- context 'when spec_helper.rb has a missing KnapsackPro::Adapters::RSpecAdapter.bind method' do
203
- it do
204
- rspec_options = ''
205
-
206
- spec_helper = <<~SPEC
207
- require 'knapsack_pro'
208
- SPEC
209
-
210
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
211
- describe 'A_describe' do
212
- it 'A1 test example' do
213
- expect(1).to eq 1
214
- end
215
- end
216
- SPEC
217
-
218
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
219
- describe 'B_describe' do
220
- it 'B1 test example' do
221
- expect(1).to eq 1
222
- end
223
- end
224
- SPEC
225
-
226
- generate_specs(spec_helper, rspec_options, [
227
- [spec_a],
228
- [spec_b],
229
- ])
230
-
231
- actual = subject
232
-
233
- expect(actual.stdout).to include('ERROR -- knapsack_pro: You forgot to call KnapsackPro::Adapters::RSpecAdapter.bind method in your test runner configuration file. It is needed to record test files time execution. Please follow the installation guide to configure your project properly https://knapsackpro.com/perma/ruby/installation-guide')
234
-
235
- expect(actual.exit_code).to eq 1
236
- end
237
- end
238
-
239
- context 'when RSpec options are not set' do
240
- before do
241
- ENV['KNAPSACK_PRO_LOG_LEVEL'] = 'info'
242
- end
243
-
244
- after do
245
- ENV.delete('KNAPSACK_PRO_LOG_LEVEL')
246
- end
247
-
248
- it 'uses a default progress formatter' do
249
- rspec_options = ''
250
-
251
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
252
- describe 'A_describe' do
253
- it {}
254
- it {}
255
- it {}
256
- end
257
- SPEC
258
-
259
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
260
- describe 'B_describe' do
261
- it {}
262
- it {}
263
- end
264
- SPEC
265
-
266
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
267
- describe 'C_describe' do
268
- it {}
269
- it {}
270
- it {}
271
- end
272
- SPEC
273
-
274
- generate_specs(spec_helper_with_knapsack, rspec_options, [
275
- [spec_a, spec_b],
276
- [spec_c],
277
- ])
278
-
279
- actual = subject
280
-
281
- beginning_of_knapsack_pro_log_info_message = 'I, ['
282
-
283
- # shows dots for the 1st batch of tests
284
- expect(actual.stdout).to include('.....' + beginning_of_knapsack_pro_log_info_message)
285
- # shows dots for the 2nd batch of tests
286
- expect(actual.stdout).to include('...' + beginning_of_knapsack_pro_log_info_message)
287
-
288
- expect(actual.exit_code).to eq 0
289
- end
290
- end
291
-
292
- context 'when RSpec options are not set AND Knapsack Pro log level is warn' do
293
- before do
294
- ENV['KNAPSACK_PRO_LOG_LEVEL'] = 'warn'
295
- ENV.delete('TEST__SHOW_DEBUG_LOG')
296
- end
297
- after do
298
- ENV.delete('KNAPSACK_PRO_LOG_LEVEL')
299
- end
300
-
301
- it 'uses a default progress formatter AND shows dots for all test examples' do
302
- rspec_options = ''
303
-
304
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
305
- describe 'A_describe' do
306
- it {}
307
- it {}
308
- it {}
309
- end
310
- SPEC
311
-
312
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
313
- describe 'B_describe' do
314
- it {}
315
- it {}
316
- end
317
- SPEC
318
-
319
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
320
- describe 'C_describe' do
321
- it {}
322
- it {}
323
- it {}
324
- end
325
- SPEC
326
-
327
- generate_specs(spec_helper_with_knapsack, rspec_options, [
328
- [spec_a, spec_b],
329
- [spec_c],
330
- ])
331
-
332
- actual = subject
333
-
334
- expect(actual.stdout).to include('.'*8)
335
-
336
- expect(actual.exit_code).to eq 0
337
- end
338
- end
339
-
340
- context 'when rails_helper file does not exist' do
341
- it 'does not require the rails_helper file when running RSpec' do
342
- rspec_options = ''
343
-
344
- spec_helper = <<~SPEC
345
- require 'knapsack_pro'
346
- KnapsackPro::Adapters::RSpecAdapter.bind
347
- SPEC
348
-
349
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
350
- describe 'A_describe' do
351
- it 'A1 test example' do
352
- expect(1).to eq 1
353
- end
354
- end
355
- SPEC
356
-
357
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
358
- describe 'B_describe' do
359
- it 'B1 test example' do
360
- expect(1).to eq 1
361
- end
362
- end
363
- SPEC
364
-
365
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
366
- describe 'C_describe' do
367
- it 'C1 test example' do
368
- expect(1).to eq 1
369
- end
370
- end
371
- SPEC
372
-
373
- generate_specs(spec_helper, rspec_options, [
374
- [spec_a, spec_b],
375
- [spec_c],
376
- ])
377
-
378
- actual = subject
379
-
380
- expect(actual.stdout).to_not include('--require rails_helper')
381
-
382
- expect(actual.exit_code).to eq 0
383
- end
384
- end
385
-
386
- context 'when rails_helper file exists' do
387
- it 'requires the rails_helper file when running RSpec and runs hooks defined within it' do
388
- rspec_options = ''
389
-
390
- spec_helper = <<~SPEC
391
- require 'knapsack_pro'
392
- KnapsackPro::Adapters::RSpecAdapter.bind
393
- SPEC
394
-
395
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
396
- describe 'A_describe' do
397
- it 'A1 test example' do
398
- expect(1).to eq 1
399
- end
400
- end
401
- SPEC
402
-
403
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
404
- describe 'B_describe' do
405
- it 'B1 test example' do
406
- expect(1).to eq 1
407
- end
408
- end
409
- SPEC
410
-
411
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
412
- describe 'C_describe' do
413
- it 'C1 test example' do
414
- expect(1).to eq 1
415
- end
416
- end
417
- SPEC
418
-
419
- generate_specs(spec_helper, rspec_options, [
420
- [spec_a, spec_b],
421
- [spec_c],
422
- ])
423
-
424
- rails_helper = <<~SPEC
425
- RSpec.configure do |config|
426
- config.before(:suite) do
427
- puts 'RSpec_before_suite_hook_from_rails_helper'
428
- end
429
- config.after(:suite) do
430
- puts 'RSpec_after_suite_hook_from_rails_helper'
431
- end
432
- end
433
- SPEC
434
-
435
- create_rails_helper_file(rails_helper)
436
-
437
- actual = subject
438
-
439
- expect(actual.stdout).to include('--require rails_helper')
440
- expect(actual.stdout.scan(/RSpec_before_suite_hook_from_rails_helper/).size).to eq 1
441
- expect(actual.stdout.scan(/RSpec_after_suite_hook_from_rails_helper/).size).to eq 1
442
-
443
- expect(actual.exit_code).to eq 0
444
- end
445
-
446
- it 'runs suite hooks defined in rails_helper only once, even if file is required multiple times' do
447
- rspec_options = ''
448
-
449
- spec_helper = <<~SPEC
450
- require 'knapsack_pro'
451
- KnapsackPro::Adapters::RSpecAdapter.bind
452
- SPEC
453
-
454
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
455
- require 'rails_helper'
456
- describe 'A_describe' do
457
- it 'A1 test example' do
458
- expect(1).to eq 1
459
- end
460
- end
461
- SPEC
462
-
463
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
464
- require 'rails_helper'
465
- describe 'B_describe' do
466
- it 'B1 test example' do
467
- expect(1).to eq 1
468
- end
469
- end
470
- SPEC
471
-
472
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
473
- require 'rails_helper'
474
- describe 'C_describe' do
475
- it 'C1 test example' do
476
- expect(1).to eq 1
477
- end
478
- end
479
- SPEC
480
-
481
- generate_specs(spec_helper, rspec_options, [
482
- [spec_a, spec_b],
483
- [spec_c],
484
- ])
485
-
486
- rails_helper = <<~SPEC
487
- RSpec.configure do |config|
488
- config.before(:suite) do
489
- puts 'RSpec_before_suite_hook_from_rails_helper'
490
- end
491
- config.after(:suite) do
492
- puts 'RSpec_after_suite_hook_from_rails_helper'
493
- end
494
- end
495
- SPEC
496
-
497
- create_rails_helper_file(rails_helper)
498
-
499
- actual = subject
500
-
501
- expect(actual.stdout.scan(/RSpec_before_suite_hook_from_rails_helper/).size).to eq 1
502
- expect(actual.stdout.scan(/RSpec_after_suite_hook_from_rails_helper/).size).to eq 1
503
-
504
- expect(actual.exit_code).to eq 0
505
- end
506
- end
507
-
508
- context 'when hooks are defined' do
509
- it 'calls RSpec before/after hooks only once for multiple batches of tests' do
510
- rspec_options = ''
511
-
512
- spec_helper = <<~SPEC
513
- require 'knapsack_pro'
514
- KnapsackPro::Adapters::RSpecAdapter.bind
515
-
516
- RSpec.configure do |config|
517
- config.before(:suite) do
518
- puts 'RSpec_before_suite_hook'
519
- end
520
- config.after(:suite) do
521
- puts 'RSpec_after_suite_hook'
522
- end
523
- end
524
- SPEC
525
-
526
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
527
- describe 'A_describe' do
528
- it 'A1 test example' do
529
- expect(1).to eq 1
530
- end
531
- end
532
- SPEC
533
-
534
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
535
- describe 'B_describe' do
536
- it 'B1 test example' do
537
- expect(1).to eq 1
538
- end
539
- end
540
- SPEC
541
-
542
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
543
- describe 'C_describe' do
544
- it 'C1 test example' do
545
- expect(1).to eq 1
546
- end
547
- end
548
- SPEC
549
-
550
- generate_specs(spec_helper, rspec_options, [
551
- [spec_a, spec_b],
552
- [spec_c],
553
- ])
554
-
555
- actual = subject
556
-
557
- expect(actual.stdout.scan(/RSpec_before_suite_hook/).size).to eq 1
558
- expect(actual.stdout.scan(/RSpec_after_suite_hook/).size).to eq 1
559
-
560
- expect(actual.exit_code).to eq 0
561
- end
562
-
563
- it 'calls queue hooks for multiple batches of tests (queue hooks can be defined multiple times)' do
564
- rspec_options = ''
565
-
566
- spec_helper = <<~SPEC
567
- require 'knapsack_pro'
568
- KnapsackPro::Adapters::RSpecAdapter.bind
569
-
570
- KnapsackPro::Hooks::Queue.before_queue do |queue_id|
571
- puts '1st before_queue - run before the test suite'
572
- end
573
- KnapsackPro::Hooks::Queue.before_queue do |queue_id|
574
- puts '2nd before_queue - run before the test suite'
575
- end
576
-
577
- KnapsackPro::Hooks::Queue.before_subset_queue do |queue_id, subset_queue_id|
578
- puts '1st before_subset_queue - run before the next subset of tests'
579
- end
580
- KnapsackPro::Hooks::Queue.before_subset_queue do |queue_id, subset_queue_id|
581
- puts '2nd before_subset_queue - run before the next subset of tests'
582
- end
583
-
584
- KnapsackPro::Hooks::Queue.after_subset_queue do |queue_id, subset_queue_id|
585
- puts '1st after_subset_queue - run after the previous subset of tests'
586
- end
587
- KnapsackPro::Hooks::Queue.after_subset_queue do |queue_id, subset_queue_id|
588
- puts '2nd after_subset_queue - run after the previous subset of tests'
589
- end
590
-
591
- KnapsackPro::Hooks::Queue.after_queue do |queue_id|
592
- puts '1st after_queue - run after the test suite'
593
- end
594
- KnapsackPro::Hooks::Queue.after_queue do |queue_id|
595
- puts '2nd after_queue - run after the test suite'
596
- end
597
- SPEC
598
-
599
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
600
- describe 'A_describe' do
601
- it 'A1 test example' do
602
- expect(1).to eq 1
603
- end
604
- end
605
- SPEC
606
-
607
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
608
- describe 'B_describe' do
609
- it 'B1 test example' do
610
- expect(1).to eq 1
611
- end
612
- end
613
- SPEC
614
-
615
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
616
- describe 'C_describe' do
617
- it 'C1 test example' do
618
- expect(1).to eq 1
619
- end
620
- end
621
- SPEC
622
-
623
- generate_specs(spec_helper, rspec_options, [
624
- [spec_a, spec_b],
625
- [spec_c],
626
- ])
627
-
628
- actual = subject
629
-
630
- expect(actual.stdout.scan(/1st before_queue - run before the test suite/).size).to eq 1
631
- expect(actual.stdout.scan(/2nd before_queue - run before the test suite/).size).to eq 1
632
- expect(actual.stdout.scan(/1st before_subset_queue - run before the next subset of tests/).size).to eq 2
633
- expect(actual.stdout.scan(/2nd before_subset_queue - run before the next subset of tests/).size).to eq 2
634
- expect(actual.stdout.scan(/1st after_subset_queue - run after the previous subset of tests/).size).to eq 2
635
- expect(actual.stdout.scan(/2nd after_subset_queue - run after the previous subset of tests/).size).to eq 2
636
- expect(actual.stdout.scan(/1st after_queue - run after the test suite/).size).to eq 1
637
- expect(actual.stdout.scan(/2nd after_queue - run after the test suite/).size).to eq 1
638
-
639
- expect(actual.exit_code).to eq 0
640
- end
641
-
642
- it 'calls hooks defined with when_first_matching_example_defined only once for multiple batches of tests' do
643
- rspec_options = '--format documentation'
644
-
645
- spec_helper = <<~SPEC
646
- require 'knapsack_pro'
647
- KnapsackPro::Adapters::RSpecAdapter.bind
648
-
649
- def when_first_matching_example_defined(type:)
650
- env_var_name = "WHEN_FIRST_MATCHING_EXAMPLE_DEFINED_FOR_" + type.to_s.upcase
651
-
652
- RSpec.configure do |config|
653
- config.when_first_matching_example_defined(type: type) do
654
- config.before(:context) do
655
- unless ENV[env_var_name]
656
- yield
657
- end
658
- ENV[env_var_name] = 'hook_called'
659
- end
660
- end
661
- end
662
- end
663
-
664
- when_first_matching_example_defined(type: :model) do
665
- puts 'RSpec_custom_hook_called_once_for_model'
666
- end
667
-
668
- when_first_matching_example_defined(type: :system) do
669
- puts 'RSpec_custom_hook_called_once_for_system'
670
- end
671
-
672
- RSpec.configure do |config|
673
- config.before(:suite) do
674
- puts 'RSpec_before_suite_hook'
675
- end
676
-
677
- config.when_first_matching_example_defined(type: :model) do
678
- config.before(:suite) do
679
- puts 'RSpec_before_suite_hook_for_model'
680
- end
681
- end
682
-
683
- config.when_first_matching_example_defined(type: :system) do
684
- config.before(:suite) do
685
- puts 'RSpec_before_suite_hook_for_system'
686
- end
687
- end
688
- end
689
- SPEC
690
-
691
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
692
- describe 'A_describe', type: :model do
693
- it 'A1 test example' do
694
- expect(1).to eq 1
695
- end
696
- end
697
- SPEC
698
-
699
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
700
- describe 'B_describe', type: :system do
701
- it 'B1 test example' do
702
- expect(1).to eq 1
703
- end
704
- end
705
- SPEC
706
-
707
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
708
- describe 'C_describe' do
709
- it 'C1 test example' do
710
- expect(1).to eq 1
711
- end
712
-
713
- it 'C1 test example', :model do
714
- expect(1).to eq 1
715
- end
716
- end
717
- SPEC
718
-
719
- spec_d = Spec.new('d_spec.rb', <<~SPEC)
720
- describe 'D_describe', type: :system do
721
- it 'D1 test example' do
722
- expect(1).to eq 1
723
- end
724
- end
725
- SPEC
726
-
727
- generate_specs(spec_helper, rspec_options, [
728
- [spec_a],
729
- [spec_b],
730
- [spec_c],
731
- [spec_d],
732
- ])
733
-
734
- actual = subject
735
-
736
- expect(actual.stdout.scan(/RSpec_before_suite_hook/).size).to eq 1
737
-
738
- # skips before(:suite) hooks that were defined too late in 1st & 2nd batch of tests after before(:suite) hook is already executed
739
- expect(actual.stdout.scan(/RSpec_before_suite_hook_for_model/).size).to eq 0
740
- expect(actual.stdout.scan(/RSpec_before_suite_hook_for_system/).size).to eq 0
741
-
742
- expect(actual.stdout.scan(/RSpec_custom_hook_called_once_for_model/).size).to eq 1
743
- expect(actual.stdout.scan(/RSpec_custom_hook_called_once_for_system/).size).to eq 1
744
-
745
- expect(actual.exit_code).to eq 0
746
- end
747
-
748
- it 'gives access to batch of tests in queue hooks' do
749
- rspec_options = ''
750
-
751
- spec_helper = <<~SPEC
752
- require 'knapsack_pro'
753
- KnapsackPro::Adapters::RSpecAdapter.bind
754
-
755
- KnapsackPro::Hooks::Queue.before_subset_queue do |queue_id, subset_queue_id, queue|
756
- print "Tests in batches in before_subset_queue: "
757
- puts queue.map(&:test_file_paths).inspect
758
-
759
- print "Batches' statuses in before_subset_queue: "
760
- puts queue.map(&:status).inspect
761
- end
762
-
763
- KnapsackPro::Hooks::Queue.after_subset_queue do |queue_id, subset_queue_id, queue|
764
- print "Tests in batches in after_subset_queue: "
765
- puts queue.map(&:test_file_paths).inspect
766
- print "Batches' statuses in after_subset_queue: "
767
- puts queue.map(&:status).inspect
768
-
769
- # call public API methods that must be backward compatible
770
- print "Current batch tests: "
771
- puts queue.current_batch.test_file_paths.inspect
772
- print "Current batch status: "
773
- puts queue.current_batch.status
774
- end
775
- SPEC
776
-
777
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
778
- describe 'A_describe' do
779
- it 'A1 test example' do
780
- expect(1).to eq 1
781
- end
782
- end
783
- SPEC
784
-
785
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
786
- describe 'B_describe' do
787
- it 'B1 test example' do
788
- expect(1).to eq 1
789
- end
790
- end
791
- SPEC
792
-
793
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
794
- describe 'C_describe' do
795
- it 'C1 test example' do
796
- expect(1).to eq 1
797
- end
798
- end
799
- SPEC
800
-
801
- failing_spec_d = Spec.new('d_spec.rb', <<~SPEC)
802
- describe 'D_describe' do
803
- it 'D1 test example' do
804
- expect(1).to eq 0
805
- end
806
- end
807
- SPEC
808
-
809
- spec_e = Spec.new('e_spec.rb', <<~SPEC)
810
- describe 'E_describe' do
811
- it 'E1 test example' do
812
- expect(1).to eq 1
813
- end
814
- end
815
- SPEC
816
-
817
- spec_f = Spec.new('f_spec.rb', <<~SPEC)
818
- describe 'F_describe' do
819
- it 'F1 test example' do
820
- expect(1).to eq 1
821
- end
822
- end
823
- SPEC
824
-
825
- failing_spec_g = Spec.new('g_spec.rb', <<~SPEC)
826
- describe 'G_describe' do
827
- it 'G1 test example' do
828
- expect(1).to eq 0
829
- end
830
- end
831
- SPEC
832
-
833
- spec_h = Spec.new('h_spec.rb', <<~SPEC)
834
- describe 'h_describe' do
835
- it 'H1 test example' do
836
- expect(1).to eq 1
837
- end
838
- end
839
- SPEC
840
-
841
- generate_specs(spec_helper, rspec_options, [
842
- [spec_a, spec_b],
843
- [spec_c, failing_spec_d],
844
- [spec_e, spec_f],
845
- [failing_spec_g, spec_h],
846
- ])
847
-
848
- actual = subject
849
-
850
- expect(actual.stdout).to include('Tests in batches in before_subset_queue: [["spec_integration/a_spec.rb", "spec_integration/b_spec.rb"]]')
851
- expect(actual.stdout).to include('Tests in batches in before_subset_queue: [["spec_integration/a_spec.rb", "spec_integration/b_spec.rb"], ["spec_integration/c_spec.rb", "spec_integration/d_spec.rb"]]')
852
- expect(actual.stdout).to include('Tests in batches in before_subset_queue: [["spec_integration/a_spec.rb", "spec_integration/b_spec.rb"], ["spec_integration/c_spec.rb", "spec_integration/d_spec.rb"], ["spec_integration/e_spec.rb", "spec_integration/f_spec.rb"]]')
853
- expect(actual.stdout).to include('Tests in batches in before_subset_queue: [["spec_integration/a_spec.rb", "spec_integration/b_spec.rb"], ["spec_integration/c_spec.rb", "spec_integration/d_spec.rb"], ["spec_integration/e_spec.rb", "spec_integration/f_spec.rb"], ["spec_integration/g_spec.rb", "spec_integration/h_spec.rb"]]')
854
-
855
- expect(actual.stdout).to include('Tests in batches in after_subset_queue: [["spec_integration/a_spec.rb", "spec_integration/b_spec.rb"]]')
856
- expect(actual.stdout).to include('Tests in batches in after_subset_queue: [["spec_integration/a_spec.rb", "spec_integration/b_spec.rb"], ["spec_integration/c_spec.rb", "spec_integration/d_spec.rb"]]')
857
- expect(actual.stdout).to include('Tests in batches in after_subset_queue: [["spec_integration/a_spec.rb", "spec_integration/b_spec.rb"], ["spec_integration/c_spec.rb", "spec_integration/d_spec.rb"], ["spec_integration/e_spec.rb", "spec_integration/f_spec.rb"]]')
858
- expect(actual.stdout).to include('Tests in batches in after_subset_queue: [["spec_integration/a_spec.rb", "spec_integration/b_spec.rb"], ["spec_integration/c_spec.rb", "spec_integration/d_spec.rb"], ["spec_integration/e_spec.rb", "spec_integration/f_spec.rb"], ["spec_integration/g_spec.rb", "spec_integration/h_spec.rb"]]')
859
-
860
-
861
- expect(actual.stdout).to include("Batches' statuses in before_subset_queue: [:not_executed]")
862
- expect(actual.stdout).to include("Batches' statuses in before_subset_queue: [:passed, :not_executed]")
863
- expect(actual.stdout).to include("Batches' statuses in before_subset_queue: [:passed, :failed, :not_executed]")
864
- expect(actual.stdout).to include("Batches' statuses in before_subset_queue: [:passed, :failed, :passed, :not_executed]")
865
-
866
- expect(actual.stdout).to include("Batches' statuses in after_subset_queue: [:passed]")
867
- expect(actual.stdout).to include("Batches' statuses in after_subset_queue: [:passed, :failed]")
868
- expect(actual.stdout).to include("Batches' statuses in after_subset_queue: [:passed, :failed, :passed]")
869
- expect(actual.stdout).to include("Batches' statuses in after_subset_queue: [:passed, :failed, :passed, :failed]")
870
-
871
- expect(actual.stdout).to include('Current batch tests: ["spec_integration/a_spec.rb", "spec_integration/b_spec.rb"]')
872
- expect(actual.stdout).to include('Current batch tests: ["spec_integration/c_spec.rb", "spec_integration/d_spec.rb"]')
873
- expect(actual.stdout).to include('Current batch tests: ["spec_integration/e_spec.rb", "spec_integration/f_spec.rb"]')
874
- expect(actual.stdout).to include('Current batch tests: ["spec_integration/g_spec.rb", "spec_integration/h_spec.rb"]')
875
- expect(actual.stdout).to include('Current batch status: passed').twice
876
- expect(actual.stdout).to include('Current batch status: failed').twice
877
-
878
- expect(actual.exit_code).to eq 1
879
- end
880
- end
881
-
882
- context 'when the RSpec seed is used' do
883
- it do
884
- rspec_options = '--order rand:123'
885
-
886
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
887
- describe 'A_describe' do
888
- it 'A1 test example' do
889
- expect(1).to eq 1
890
- end
891
- end
892
- SPEC
893
-
894
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
895
- describe 'B_describe' do
896
- it 'B1 test example' do
897
- expect(1).to eq 1
898
- end
899
- end
900
- SPEC
901
-
902
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
903
- describe 'C_describe' do
904
- it 'C1 test example' do
905
- expect(1).to eq 1
906
- end
907
- end
908
- SPEC
909
-
910
- generate_specs(spec_helper_with_knapsack, rspec_options, [
911
- [spec_a, spec_b],
912
- [spec_c],
913
- ])
914
-
915
- actual = subject
916
-
917
- expect(actual.stdout).to include('Randomized with seed 123')
918
-
919
- # 1st batch
920
- expect(actual.stdout).to include('INFO -- knapsack_pro: bundle exec rspec --order rand:123 --format progress --default-path spec_integration "spec_integration/a_spec.rb" "spec_integration/b_spec.rb"')
921
- # 2nd batch
922
- expect(actual.stdout).to include('INFO -- knapsack_pro: bundle exec rspec --order rand:123 --format progress --default-path spec_integration "spec_integration/c_spec.rb"')
923
-
924
- # the final RSpec command with seed
925
- expect(actual.stdout).to include('INFO -- knapsack_pro: bundle exec rspec --order rand:123 --format progress --default-path spec_integration "spec_integration/a_spec.rb" "spec_integration/b_spec.rb" "spec_integration/c_spec.rb"')
926
-
927
- expect(actual.exit_code).to eq 0
928
- end
929
- end
930
-
931
- context 'when a failing test in a batch of tests that is not the last batch fetched from the Queue API' do
932
- it 'returns 1 as exit code (it remembers that one of the batches has a failing test)' do
933
- rspec_options = '--format documentation'
934
-
935
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
936
- describe 'A_describe' do
937
- it 'A1 test example' do
938
- expect(1).to eq 1
939
- end
940
- end
941
- SPEC
942
-
943
- failing_spec = Spec.new('failing_spec.rb', <<~SPEC)
944
- describe 'B_describe' do
945
- it 'B1 test example' do
946
- expect(1).to eq 0
947
- end
948
- end
949
- SPEC
950
-
951
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
952
- describe 'C_describe' do
953
- it 'C1 test example' do
954
- expect(1).to eq 1
955
- end
956
- end
957
- SPEC
958
-
959
- generate_specs(spec_helper_with_knapsack, rspec_options, [
960
- [spec_a, failing_spec],
961
- [spec_c],
962
- ])
963
-
964
- actual = subject
965
-
966
- expect(actual.stdout).to include('B1 test example (FAILED - 1)')
967
- expect(actual.stdout).to include('Failure/Error: expect(1).to eq 0')
968
- expect(actual.stdout).to include('3 examples, 1 failure')
969
-
970
- expect(actual.exit_code).to eq 1
971
- end
972
- end
973
-
974
- context 'when a failing test raises an exception' do
975
- it 'returns 1 as exit code AND the exception does not leak outside of the RSpec runner context' do
976
- rspec_options = '--format documentation'
977
-
978
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
979
- describe 'A_describe' do
980
- it 'A1 test example' do
981
- expect(1).to eq 1
982
- end
983
- end
984
- SPEC
985
-
986
- failing_spec = Spec.new('failing_spec.rb', <<~SPEC)
987
- describe 'B_describe' do
988
- it 'B1 test example' do
989
- raise 'A custom exception from a test'
990
- end
991
- end
992
- SPEC
993
-
994
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
995
- describe 'C_describe' do
996
- it 'C1 test example' do
997
- expect(1).to eq 1
998
- end
999
- end
1000
- SPEC
1001
-
1002
- generate_specs(spec_helper_with_knapsack, rspec_options, [
1003
- [spec_a, failing_spec],
1004
- [spec_c],
1005
- ])
1006
-
1007
- actual = subject
1008
-
1009
- expect(actual.stdout).to include('B1 test example (FAILED - 1)')
1010
- expect(actual.stdout).to include("Failure/Error: raise 'A custom exception from a test'")
1011
- expect(actual.stdout).to include('3 examples, 1 failure')
1012
-
1013
- expect(actual.exit_code).to eq 1
1014
- end
1015
- end
1016
-
1017
- context 'when a spec file has a syntax error outside of the test example' do
1018
- it 'stops running tests on the batch that has a test file with the syntax error AND returns 1 as exit code' do
1019
- rspec_options = '--format documentation'
1020
-
1021
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
1022
- describe 'A_describe' do
1023
- it 'A1 test example' do
1024
- expect(1).to eq 1
1025
- end
1026
- end
1027
- SPEC
1028
-
1029
- failing_spec = Spec.new('failing_spec.rb', <<~SPEC)
1030
- describe 'B_describe' do
1031
- a_fake_method
1032
-
1033
- it 'B1 test example' do
1034
- expect(1).to eq 1
1035
- end
1036
- end
1037
- SPEC
1038
-
1039
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
1040
- describe 'C_describe' do
1041
- it 'C1 test example' do
1042
- expect(1).to eq 1
1043
- end
1044
- end
1045
- SPEC
1046
-
1047
- generate_specs(spec_helper_with_knapsack, rspec_options, [
1048
- [spec_a],
1049
- [failing_spec],
1050
- [spec_c],
1051
- ])
1052
-
1053
- actual = subject
1054
-
1055
- # 1st batch of tests executed correctly
1056
- expect(actual.stdout).to include('A1 test example')
1057
- # 2nd batch contains the test file that cannot be loaded and the test file is not executed
1058
- expect(actual.stdout).to_not include('B1 test example')
1059
- # 3rd batch is never executed
1060
- expect(actual.stdout).to_not include('C1 test example')
1061
-
1062
- expect(actual.stdout).to include('An error occurred while loading ./spec_integration/failing_spec.rb')
1063
- expect(actual.stdout).to match(/undefined local variable or method .a_fake_method. for.* RSpec::ExampleGroups::BDescribe/)
1064
- expect(actual.stdout).to include('WARN -- knapsack_pro: RSpec wants to quit')
1065
- expect(actual.stdout).to include('1 example, 0 failures, 1 error occurred outside of examples')
1066
-
1067
- expect(actual.exit_code).to eq 1
1068
- end
1069
- end
1070
-
1071
- context 'when a syntax error (an exception) in spec_helper.rb' do
1072
- it 'exits early with 1 as the exit code without running tests because RSpec wants to quit' do
1073
- rspec_options = '--format documentation'
1074
-
1075
- spec_helper = <<~SPEC
1076
- require 'knapsack_pro'
1077
- KnapsackPro::Adapters::RSpecAdapter.bind
1078
-
1079
- a_fake_method
1080
- SPEC
1081
-
1082
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
1083
- describe 'A_describe' do
1084
- it 'A1 test example' do
1085
- expect(1).to eq 1
1086
- end
1087
- end
1088
- SPEC
1089
-
1090
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
1091
- describe 'B_describe' do
1092
- it 'B1 test example' do
1093
- expect(1).to eq 1
1094
- end
1095
- end
1096
- SPEC
1097
-
1098
- generate_specs(spec_helper, rspec_options, [
1099
- [spec_a],
1100
- [spec_b],
1101
- ])
1102
-
1103
- actual = subject
1104
-
1105
- expect(actual.stdout).to include('An error occurred while loading spec_helper.')
1106
- expect(actual.stdout).to match(/undefined local variable or method .a_fake_method. for main/)
1107
- expect(actual.stdout).to include('0 examples, 0 failures, 1 error occurred outside of examples')
1108
-
1109
- expect(actual.exit_code).to eq 1
1110
- end
1111
- end
1112
-
1113
- # Based on:
1114
- # https://github.com/rspec/rspec-core/pull/2926/files
1115
- context 'when RSpec is quitting' do
1116
- let(:helper_with_exit_location) { "#{SPEC_DIRECTORY}/helper_with_exit.rb" }
1117
-
1118
- it 'returns non zero exit code because RSpec is quitting' do
1119
- skip 'Not supported by this RSpec version' if RSpec::Core::Version::STRING == '3.10.2'
1120
-
1121
- File.open(helper_with_exit_location, 'w') { |file| file.write('exit 123') }
1122
-
1123
- rspec_options = "--format documentation --require ./#{helper_with_exit_location}"
1124
-
1125
- spec_helper = <<~SPEC
1126
- require 'knapsack_pro'
1127
- KnapsackPro::Adapters::RSpecAdapter.bind
1128
- SPEC
1129
-
1130
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
1131
- describe 'A_describe' do
1132
- it 'A1 test example' do
1133
- expect(1).to eq 1
1134
- end
1135
- end
1136
- SPEC
1137
-
1138
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
1139
- describe 'B_describe' do
1140
- it 'B1 test example' do
1141
- expect(1).to eq 1
1142
- end
1143
- end
1144
- SPEC
1145
-
1146
- generate_specs(spec_helper, rspec_options, [
1147
- [spec_a],
1148
- [spec_b],
1149
- ])
1150
-
1151
- actual = subject
1152
-
1153
- expect(actual.stdout).to include('While loading ./spec_integration/helper_with_exit.rb an `exit` / `raise SystemExit` occurred, RSpec will now quit.')
1154
-
1155
- expect(actual.stdout).to_not include('A1 test example')
1156
- expect(actual.stdout).to_not include('B1 test example')
1157
-
1158
- expect(actual.exit_code).to eq 123
1159
- end
1160
- end
1161
-
1162
- context 'when the test suite has pending tests' do
1163
- it 'shows the summary of pending tests' do
1164
- rspec_options = '--format documentation'
1165
-
1166
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
1167
- describe 'A_describe' do
1168
- it 'A1 test example' do
1169
- expect(1).to eq 1
1170
- end
1171
- end
1172
- SPEC
1173
-
1174
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
1175
- describe 'B_describe' do
1176
- xit 'B1 test example' do
1177
- expect(1).to eq 1
1178
- end
1179
- end
1180
- SPEC
1181
-
1182
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
1183
- describe 'C_describe' do
1184
- it 'C1 test example' do
1185
- expect(1).to eq 1
1186
- end
1187
-
1188
- xit 'C2 test example' do
1189
- expect(1).to eq 1
1190
- end
1191
- end
1192
- SPEC
1193
-
1194
- generate_specs(spec_helper_with_knapsack, rspec_options, [
1195
- [spec_a, spec_b],
1196
- [spec_c],
1197
- ])
1198
-
1199
- actual = subject
1200
-
1201
- expect(actual.stdout).to include('B1 test example (PENDING: Temporarily skipped with xit)')
1202
- expect(actual.stdout).to include('C2 test example (PENDING: Temporarily skipped with xit)')
1203
-
1204
- expect(actual.stdout).to include("Pending: (Failures listed here are expected and do not affect your suite's status)")
1205
- expect(actual.stdout).to include('1) B_describe B1 test example')
1206
- expect(actual.stdout).to include('2) C_describe C2 test example')
1207
-
1208
- expect(actual.stdout).to include('4 examples, 0 failures, 2 pending')
1209
-
1210
- expect(actual.exit_code).to eq 0
1211
- end
1212
- end
1213
-
1214
- context 'when a test file raises an exception that cannot be handle by RSpec' do
1215
- it 'stops running tests when unhandled exception happens AND sets 1 as exit code AND shows summary of unexecuted tests' do
1216
- rspec_options = '--format documentation'
1217
-
1218
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
1219
- describe 'A_describe' do
1220
- it 'A1 test example' do
1221
- expect(1).to eq 1
1222
- end
1223
- end
1224
- SPEC
1225
-
1226
- # list of unhandled exceptions:
1227
- # RSpec::Support::AllExceptionsExceptOnesWeMustNotRescue::AVOID_RESCUING
1228
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
1229
- describe 'B_describe' do
1230
- it 'B1 test example' do
1231
- raise NoMemoryError.new
1232
- end
1233
- end
1234
- SPEC
1235
-
1236
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
1237
- describe 'C_describe' do
1238
- it 'C1 test example' do
1239
- expect(1).to eq 1
1240
- end
1241
- end
1242
- SPEC
1243
-
1244
- generate_specs(spec_helper_with_knapsack, rspec_options, [
1245
- [spec_a],
1246
- [spec_b],
1247
- [spec_c],
1248
- ])
1249
-
1250
- actual = subject
1251
-
1252
- expect(actual.stdout).to include('A1 test example')
1253
-
1254
- expect(actual.stdout).to include('B_describe')
1255
- expect(actual.stdout).to include('An unexpected exception happened. RSpec cannot handle it. The exception: #<NoMemoryError: NoMemoryError>')
1256
- expect(actual.stdout).to include('Exception message: ')
1257
- expect(actual.stdout).to include('Exception backtrace: ')
1258
- expect(actual.stdout).to_not include('B1 test example')
1259
-
1260
- expect(actual.stdout).to_not include('C1 test example')
1261
-
1262
- # 2nd test example raised unhandled exception during runtime.
1263
- # It breaks RSpec so it was not marked as failed.
1264
- expect(actual.stdout).to include('2 examples, 0 failures')
1265
-
1266
- expect(actual.stdout).to include('WARN -- knapsack_pro: Unexecuted tests on this CI node (including pending tests): spec_integration/b_spec.rb')
1267
-
1268
- expect(actual.exit_code).to eq 1
1269
- end
1270
- end
1271
-
1272
- context 'when a test file raises an exception that cannot be handle by RSpec AND --error-exit-code is set' do
1273
- it 'sets a custom exit code' do
1274
- rspec_options = '--format documentation --error-exit-code 2'
1275
-
1276
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
1277
- describe 'A_describe' do
1278
- it 'A1 test example' do
1279
- expect(1).to eq 1
1280
- end
1281
- end
1282
- SPEC
1283
-
1284
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
1285
- describe 'B_describe' do
1286
- it 'B1 test example' do
1287
- raise NoMemoryError.new
1288
- end
1289
- end
1290
- SPEC
1291
-
1292
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
1293
- describe 'C_describe' do
1294
- it 'C1 test example' do
1295
- expect(1).to eq 1
1296
- end
1297
- end
1298
- SPEC
1299
-
1300
- generate_specs(spec_helper_with_knapsack, rspec_options, [
1301
- [spec_a],
1302
- [spec_b],
1303
- [spec_c],
1304
- ])
1305
-
1306
- actual = subject
1307
-
1308
- expect(actual.exit_code).to eq 2
1309
- end
1310
- end
1311
-
1312
- context 'when a termination signal is received by the process' do
1313
- it 'terminates the process after tests from the current RSpec ExampleGroup are executed and sets 1 as exit code' do
1314
- rspec_options = '--format documentation'
1315
-
1316
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
1317
- describe 'A_describe' do
1318
- it 'A1 test example' do
1319
- expect(1).to eq 1
1320
-
1321
- Thread.new do
1322
- sleep 10
1323
- end
1324
-
1325
- sleep 1 # wait for the above async thread to start
1326
- end
1327
- end
1328
- SPEC
1329
-
1330
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
1331
- describe 'B1_describe' do
1332
- describe 'B1.1_describe' do
1333
- xit 'B1.1.1 test example' do
1334
- expect(1).to eq 1
1335
- end
1336
- it 'B1.1.2 test example' do
1337
- Process.kill("INT", Process.pid)
1338
- end
1339
- it 'B1.1.3 test example' do
1340
- expect(1).to eq 0
1341
- end
1342
- end
1343
-
1344
- describe 'B1.2_describe' do
1345
- it 'B1.2.1 test example' do
1346
- expect(1).to eq 1
1347
- end
1348
- end
1349
- end
1350
-
1351
- describe 'B2_describe' do
1352
- it 'B2.1 test example' do
1353
- expect(1).to eq 1
1354
- end
1355
- end
1356
- SPEC
1357
-
1358
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
1359
- describe 'C_describe' do
1360
- it 'C1 test example' do
1361
- expect(1).to eq 1
1362
- end
1363
- end
1364
- SPEC
1365
-
1366
- spec_d = Spec.new('d_spec.rb', <<~SPEC)
1367
- describe 'D_describe' do
1368
- it 'D1 test example' do
1369
- expect(1).to eq 1
1370
- end
1371
- end
1372
- SPEC
1373
-
1374
- generate_specs(spec_helper_with_knapsack, rspec_options, [
1375
- [spec_a],
1376
- [spec_b, spec_c],
1377
- [spec_d],
1378
- ])
1379
-
1380
- actual = subject
1381
-
1382
- expect(actual.stdout).to include('B1.1.1 test example (PENDING: Temporarily skipped with xit)')
1383
- expect(actual.stdout).to include('INT signal has been received. Terminating Knapsack Pro...')
1384
- expect(actual.stdout).to include('B1.1.2 test example')
1385
- expect(actual.stdout).to_not include('B1.1.3 test example (FAILED - 1)')
1386
- expect(actual.stdout).to_not include('B1.2.1 test example')
1387
-
1388
- # next ExampleGroup within the same b_spec.rb is not executed
1389
- expect(actual.stdout).to_not include('B2.1 test example')
1390
-
1391
- # next test file from the same batch is not executed
1392
- expect(actual.stdout).to_not include('C1 test example')
1393
-
1394
- # next batch of tests is not pulled from the Queue API and is not executed
1395
- expect(actual.stdout).to_not include('D1 test example')
1396
-
1397
-
1398
- expect(actual.stdout).to include(
1399
- <<~OUTPUT
1400
- Pending: (Failures listed here are expected and do not affect your suite's status)
1401
-
1402
- 1) B1_describe B1.1_describe B1.1.1 test example
1403
- OUTPUT
1404
- )
1405
-
1406
- expect(actual.stdout).to include('To retry the last batch of tests fetched from the Queue API, please run the following command on your machine:')
1407
- expect(actual.stdout).to include('bundle exec rspec --format documentation --default-path spec_integration "spec_integration/b_spec.rb" "spec_integration/c_spec.rb"')
1408
-
1409
- expect(actual.stdout).to include('Use the following backtrace(s) to find the line of code that got stuck if the CI node hung and terminated your tests.')
1410
- expect(actual.stdout).to include('Running specs in the main thread:')
1411
- expect(actual.stdout).to include('Running specs in non-main thread:')
1412
- expect(actual.stdout).to include('Main thread backtrace:')
1413
- expect(actual.stdout.scan(/spec_integration\/b_spec\.rb:7:in .*kill/).size).to eq 2
1414
- expect(actual.stdout).to include('Non-main thread backtrace:')
1415
- expect(actual.stdout.scan(/spec_integration\/a_spec\.rb:6:in .*sleep/).size).to eq 2
1416
-
1417
-
1418
- expect(actual.exit_code).to eq 1
1419
- end
1420
- end
1421
-
1422
- context 'when a termination signal is received by the process AND --error-exit-code is set' do
1423
- it 'terminates the process AND sets a custom exit code' do
1424
- rspec_options = '--format documentation --error-exit-code 3'
1425
-
1426
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
1427
- describe 'A_describe' do
1428
- it 'A1 test example' do
1429
- expect(1).to eq 1
1430
- end
1431
- end
1432
- SPEC
1433
-
1434
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
1435
- describe 'B_describe' do
1436
- it 'B1 test example' do
1437
- Process.kill("INT", Process.pid)
1438
- end
1439
- end
1440
- SPEC
1441
-
1442
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
1443
- describe 'C_describe' do
1444
- it 'C1 test example' do
1445
- expect(1).to eq 1
1446
- end
1447
- end
1448
- SPEC
1449
-
1450
- generate_specs(spec_helper_with_knapsack, rspec_options, [
1451
- [spec_a],
1452
- [spec_b],
1453
- [spec_c],
1454
- ])
1455
-
1456
- actual = subject
1457
-
1458
- expect(actual.stdout).to include('INT signal has been received. Terminating Knapsack Pro...')
1459
-
1460
- expect(actual.exit_code).to eq 3
1461
- end
1462
- end
1463
-
1464
- context 'when deprecated run_all_when_everything_filtered option is true' do
1465
- it 'shows an error message AND sets 1 as exit code' do
1466
- rspec_options = '--format documentation'
1467
-
1468
- spec_helper = <<~SPEC
1469
- require 'knapsack_pro'
1470
- KnapsackPro::Adapters::RSpecAdapter.bind
1471
-
1472
- RSpec.configure do |config|
1473
- config.run_all_when_everything_filtered = true
1474
- end
1475
- SPEC
1476
-
1477
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
1478
- describe 'A_describe' do
1479
- it 'A1 test example' do
1480
- expect(1).to eq 1
1481
- end
1482
- end
1483
- SPEC
1484
-
1485
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
1486
- describe 'B_describe' do
1487
- it 'B1 test example' do
1488
- expect(1).to eq 1
1489
- end
1490
- end
1491
- SPEC
1492
-
1493
- generate_specs(spec_helper, rspec_options, [
1494
- [spec_a],
1495
- [spec_b],
1496
- ])
1497
-
1498
- actual = subject
1499
-
1500
- expect(actual.stdout).to include('ERROR -- knapsack_pro: The run_all_when_everything_filtered option is deprecated. See: https://knapsackpro.com/perma/ruby/rspec-deprecated-run-all-when-everything-filtered')
1501
-
1502
- expect(actual.stdout).to_not include('A1 test example')
1503
- expect(actual.stdout).to_not include('B1 test example')
1504
-
1505
- expect(actual.exit_code).to eq 1
1506
- end
1507
- end
1508
-
1509
- context 'when filter_run_when_matching is set to :focus and some tests are tagged with the focus tag' do
1510
- it 'shows an error message for :focus tagged tests AND sets 1 as exit code (shows the error because the batch of tests that has no focus tagged tests will run tests instead of not running them)' do
1511
- rspec_options = '--format documentation'
1512
-
1513
- spec_helper = <<~SPEC
1514
- require 'knapsack_pro'
1515
- KnapsackPro::Adapters::RSpecAdapter.bind
1516
-
1517
- RSpec.configure do |config|
1518
- config.filter_run_when_matching :focus
1519
- end
1520
- SPEC
1521
-
1522
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
1523
- describe 'A_describe' do
1524
- it 'A1 test example' do
1525
- expect(1).to eq 1
1526
- end
1527
- end
1528
- SPEC
1529
-
1530
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
1531
- describe 'B_describe' do
1532
- it 'B1 test example', :focus do
1533
- expect(1).to eq 1
1534
- end
1535
- it 'B2 test example' do
1536
- expect(1).to eq 1
1537
- end
1538
- end
1539
- SPEC
1540
-
1541
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
1542
- describe 'C_describe' do
1543
- it 'C1 test example' do
1544
- expect(1).to eq 1
1545
- end
1546
- end
1547
- SPEC
1548
-
1549
- generate_specs(spec_helper, rspec_options, [
1550
- [spec_a],
1551
- [spec_b],
1552
- [spec_c],
1553
- ])
1554
-
1555
- actual = subject
1556
-
1557
- expect(actual.stdout).to include('A1 test example')
1558
-
1559
- expect(actual.stdout).to include('B1 test example (FAILED - 1)')
1560
- expect(actual.stdout).to_not include('B2 test example') # skips B2 test due to tagged B1
1561
-
1562
- expect(actual.stdout).to include('C1 test example')
1563
-
1564
- expect(actual.stdout).to include('Knapsack Pro found an example tagged with focus in spec_integration/b_spec.rb, please remove it. See more: https://knapsackpro.com/perma/ruby/rspec-skips-tests')
1565
-
1566
- expect(actual.exit_code).to eq 1
1567
- end
1568
- end
1569
-
1570
- context 'when the late CI node has an empty batch of tests because other CI nodes already consumed tests from the Queue API' do
1571
- it 'sets 0 as exit code' do
1572
- rspec_options = '--format documentation'
1573
-
1574
- generate_specs(spec_helper_with_knapsack, rspec_options, [])
1575
-
1576
- actual = subject
1577
-
1578
- expect(actual.stdout).to include('0 examples, 0 failures')
1579
- expect(actual.stdout).to include('WARN -- knapsack_pro: No test files were executed on this CI node.')
1580
- expect(actual.stdout).to include('DEBUG -- knapsack_pro: This CI node likely started work late after the test files were already executed by other CI nodes consuming the queue.')
1581
-
1582
- expect(actual.exit_code).to eq 0
1583
- end
1584
- end
1585
-
1586
- context 'when the fail_if_no_examples option is true AND the late CI node has an empty batch of tests because other CI nodes already consumed tests from the Queue API' do
1587
- it 'sets 0 as exit code to ignore the fail_if_no_examples option' do
1588
- rspec_options = '--format documentation'
1589
-
1590
- spec_helper = <<~SPEC
1591
- require 'knapsack_pro'
1592
- KnapsackPro::Adapters::RSpecAdapter.bind
1593
-
1594
- RSpec.configure do |config|
1595
- config.fail_if_no_examples = true
1596
- end
1597
- SPEC
1598
-
1599
- generate_specs(spec_helper, rspec_options, [])
1600
-
1601
- actual = subject
1602
-
1603
- expect(actual.stdout).to include('0 examples, 0 failures')
1604
- expect(actual.stdout).to include('WARN -- knapsack_pro: No test files were executed on this CI node.')
1605
- expect(actual.stdout).to include('DEBUG -- knapsack_pro: This CI node likely started work late after the test files were already executed by other CI nodes consuming the queue.')
1606
-
1607
- expect(actual.exit_code).to eq 0
1608
- end
1609
- end
1610
-
1611
- context 'when the fail_if_no_examples option is true AND a batch of tests has a test file without test examples' do
1612
- it 'sets 0 as exit code to ignore the fail_if_no_examples option' do
1613
- rspec_options = '--format documentation'
1614
-
1615
- spec_helper = <<~SPEC
1616
- require 'knapsack_pro'
1617
- KnapsackPro::Adapters::RSpecAdapter.bind
1618
-
1619
- RSpec.configure do |config|
1620
- config.fail_if_no_examples = true
1621
- end
1622
- SPEC
1623
-
1624
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
1625
- describe 'A_describe' do
1626
- it 'A1 test example' do
1627
- expect(1).to eq 1
1628
- end
1629
- end
1630
- SPEC
1631
-
1632
- spec_b_with_no_examples = Spec.new('b_spec.rb', <<~SPEC)
1633
- describe 'B_describe' do
1634
- end
1635
- SPEC
1636
-
1637
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
1638
- describe 'C_describe' do
1639
- it 'C1 test example' do
1640
- expect(1).to eq 1
1641
- end
1642
- end
1643
- SPEC
1644
-
1645
- generate_specs(spec_helper, rspec_options, [
1646
- [spec_a],
1647
- [spec_b_with_no_examples],
1648
- [spec_c],
1649
- ])
1650
-
1651
- actual = subject
1652
-
1653
- expect(actual.stdout).to include('2 examples, 0 failures')
1654
-
1655
- expect(actual.exit_code).to eq 0
1656
- end
1657
- end
1658
-
1659
- context 'when tests are failing AND --failure-exit-code is set' do
1660
- it 'returns a custom exit code' do
1661
- rspec_options = '--format documentation --failure-exit-code 4'
1662
-
1663
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
1664
- describe 'A_describe' do
1665
- it 'A1 test example' do
1666
- expect(1).to eq 1
1667
- end
1668
- end
1669
- SPEC
1670
-
1671
- failing_spec = Spec.new('failing_spec.rb', <<~SPEC)
1672
- describe 'B_describe' do
1673
- it 'B1 test example' do
1674
- expect(1).to eq 0
1675
- end
1676
- end
1677
- SPEC
1678
-
1679
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
1680
- describe 'C_describe' do
1681
- it 'C1 test example' do
1682
- expect(1).to eq 1
1683
- end
1684
- end
1685
- SPEC
1686
-
1687
- generate_specs(spec_helper_with_knapsack, rspec_options, [
1688
- [spec_a, failing_spec],
1689
- [spec_c],
1690
- ])
1691
-
1692
- actual = subject
1693
-
1694
- expect(actual.stdout).to include('B1 test example (FAILED - 1)')
1695
- expect(actual.stdout).to include('Failure/Error: expect(1).to eq 0')
1696
- expect(actual.stdout).to include('3 examples, 1 failure')
1697
-
1698
- expect(actual.exit_code).to eq 4
1699
- end
1700
- end
1701
-
1702
- context 'when --profile is set' do
1703
- it 'shows top slowest examples AND top slowest example groups' do
1704
- rspec_options = '--format d --profile'
1705
-
1706
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
1707
- describe 'A_describe' do
1708
- it 'A1 test example' do
1709
- expect(1).to eq 1
1710
- end
1711
- end
1712
- SPEC
1713
-
1714
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
1715
- describe 'B_describe' do
1716
- it 'B1 test example' do
1717
- expect(1).to eq 1
1718
- end
1719
- end
1720
- SPEC
1721
-
1722
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
1723
- describe 'C_describe' do
1724
- it 'C1 test example' do
1725
- expect(1).to eq 1
1726
- end
1727
- end
1728
- SPEC
1729
-
1730
- generate_specs(spec_helper_with_knapsack, rspec_options, [
1731
- [spec_a, spec_b],
1732
- [spec_c],
1733
- ])
1734
-
1735
- actual = subject
1736
-
1737
- expect(actual.stdout).to include('Top 3 slowest examples')
1738
- expect(actual.stdout).to include('A_describe A1 test example')
1739
- expect(actual.stdout).to include('B_describe B1 test example')
1740
- expect(actual.stdout).to include('C_describe C1 test example')
1741
-
1742
- expect(actual.stdout).to include('Top 3 slowest example groups')
1743
-
1744
- expect(actual.exit_code).to eq 0
1745
- end
1746
- end
1747
-
1748
- context 'when an invalid RSpec option is set' do
1749
- it 'returns 1 as exit code AND shows an error message to stderr' do
1750
- rspec_options = '--format d --fake-rspec-option'
1751
-
1752
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
1753
- describe 'A_describe' do
1754
- it 'A1 test example' do
1755
- expect(1).to eq 1
1756
- end
1757
- end
1758
- SPEC
1759
-
1760
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
1761
- describe 'B_describe' do
1762
- it 'B1 test example' do
1763
- expect(1).to eq 1
1764
- end
1765
- end
1766
- SPEC
1767
-
1768
- generate_specs(spec_helper_with_knapsack, rspec_options, [
1769
- [spec_a],
1770
- [spec_b],
1771
- ])
1772
-
1773
- actual = subject
1774
-
1775
- expect(actual.stderr).to include('invalid option: --fake-rspec-option')
1776
-
1777
- expect(actual.exit_code).to eq 1
1778
- end
1779
- end
1780
-
1781
- context 'when --fail-fast is set' do
1782
- it 'stops running tests on the failing test AND returns 1 as exit code AND shows a warning message' do
1783
- rspec_options = '--format d --fail-fast'
1784
-
1785
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
1786
- describe 'A_describe' do
1787
- it 'A1 test example' do
1788
- expect(1).to eq 1
1789
- end
1790
- end
1791
- SPEC
1792
-
1793
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
1794
- describe 'B_describe' do
1795
- it 'B1 test example' do
1796
- expect(1).to eq 0
1797
- end
1798
- end
1799
- SPEC
1800
-
1801
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
1802
- describe 'C_describe' do
1803
- it 'C1 test example' do
1804
- expect(1).to eq 1
1805
- end
1806
- it 'C2 test example' do
1807
- expect(1).to eq 0
1808
- end
1809
- end
1810
- SPEC
1811
-
1812
- generate_specs(spec_helper_with_knapsack, rspec_options, [
1813
- [spec_a, spec_b],
1814
- [spec_c],
1815
- ])
1816
-
1817
- actual = subject
1818
-
1819
- expect(actual.stdout).to include('A1 test example')
1820
- expect(actual.stdout).to include('B1 test example')
1821
- expect(actual.stdout).to_not include('C1 test example')
1822
- expect(actual.stdout).to_not include('C2 test example')
1823
-
1824
- expect(actual.stdout).to include('WARN -- knapsack_pro: Test execution has been canceled because the RSpec --fail-fast option is enabled. It will cause other CI nodes to run tests longer because they need to consume more tests from the Knapsack Pro Queue API.')
1825
-
1826
- expect(actual.stdout).to include('2 examples, 1 failure')
1827
-
1828
- expect(actual.exit_code).to eq 1
1829
- end
1830
- end
1831
-
1832
- context 'when the fail_fast option is set with a specific number of tests' do
1833
- it 'stops running tests on the 2nd failing test AND returns 1 as exit code AND shows a warning message when fail fast limit met' do
1834
- rspec_options = '--format d'
1835
-
1836
- spec_helper = <<~SPEC
1837
- require 'knapsack_pro'
1838
- KnapsackPro::Adapters::RSpecAdapter.bind
1839
-
1840
- RSpec.configure do |config|
1841
- config.fail_fast = 2
1842
- end
1843
- SPEC
1844
-
1845
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
1846
- describe 'A_describe' do
1847
- it 'A1 test example' do
1848
- expect(1).to eq 0
1849
- end
1850
- end
1851
- SPEC
1852
-
1853
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
1854
- describe 'B_describe' do
1855
- it 'B1 test example' do
1856
- expect(1).to eq 1
1857
- end
1858
- it 'B2 test example' do
1859
- expect(1).to eq 0
1860
- end
1861
- end
1862
- SPEC
1863
-
1864
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
1865
- describe 'C_describe' do
1866
- it 'C1 test example' do
1867
- expect(1).to eq 1
1868
- end
1869
- it 'C2 test example' do
1870
- expect(1).to eq 1
1871
- end
1872
- end
1873
- SPEC
1874
-
1875
- generate_specs(spec_helper, rspec_options, [
1876
- [spec_a, spec_b],
1877
- [spec_c],
1878
- ])
1879
-
1880
- actual = subject
1881
-
1882
- expect(actual.stdout).to include('A1 test example (FAILED - 1)')
1883
- expect(actual.stdout).to include('B1 test example')
1884
- expect(actual.stdout).to include('B2 test example (FAILED - 2)')
1885
- expect(actual.stdout).to_not include('C1 test example')
1886
- expect(actual.stdout).to_not include('C2 test example')
1887
-
1888
- expect(actual.stdout).to include('WARN -- knapsack_pro: Test execution has been canceled because the RSpec --fail-fast option is enabled. It will cause other CI nodes to run tests longer because they need to consume more tests from the Knapsack Pro Queue API.')
1889
-
1890
- expect(actual.stdout).to include('3 examples, 2 failures')
1891
-
1892
- expect(actual.exit_code).to eq 1
1893
- end
1894
- end
1895
-
1896
- context 'when --tag is set' do
1897
- it 'runs only tagged test examples from multiple batches of tests fetched from the Queue API' do
1898
- rspec_options = '--format d --tag my_tag'
1899
-
1900
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
1901
- describe 'A_describe' do
1902
- it 'A1 test example' do
1903
- expect(1).to eq 1
1904
- end
1905
- it 'A2 test example', :my_tag do
1906
- expect(1).to eq 1
1907
- end
1908
- end
1909
- SPEC
1910
-
1911
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
1912
- describe 'B_describe', :my_tag do
1913
- it 'B1 test example' do
1914
- expect(1).to eq 1
1915
- end
1916
- end
1917
- SPEC
1918
-
1919
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
1920
- describe 'C_describe' do
1921
- it 'C1 test example' do
1922
- expect(1).to eq 1
1923
- end
1924
- end
1925
- SPEC
1926
-
1927
- spec_d = Spec.new('d_spec.rb', <<~SPEC)
1928
- describe 'D_describe' do
1929
- it 'D1 test example' do
1930
- expect(1).to eq 1
1931
- end
1932
- it 'D2 test example', :my_tag do
1933
- expect(1).to eq 1
1934
- end
1935
- end
1936
- SPEC
1937
-
1938
- generate_specs(spec_helper_with_knapsack, rspec_options, [
1939
- [spec_a, spec_b],
1940
- [spec_c],
1941
- [spec_d],
1942
- ])
1943
-
1944
- actual = subject
1945
-
1946
- expect(actual.stdout).to_not include('A1 test example')
1947
- expect(actual.stdout).to include('A2 test example')
1948
-
1949
- expect(actual.stdout).to include('B1 test example')
1950
-
1951
- expect(actual.stdout).to_not include('C1 test example')
1952
-
1953
- expect(actual.stdout).to_not include('D1 test example')
1954
- expect(actual.stdout).to include('D2 test example')
1955
-
1956
- expect(actual.stdout).to include('3 examples, 0 failures')
1957
-
1958
- expect(actual.exit_code).to eq 0
1959
- end
1960
- end
1961
-
1962
- context 'when the RSpec split by test examples is enabled' do
1963
- before do
1964
- # Remember to stub the Queue API batches to include test examples (example: a_spec.rb[1:1])
1965
- # for the following slow test files.
1966
- ENV['KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN'] = "#{SPEC_DIRECTORY}/a_spec.rb"
1967
-
1968
- ENV['KNAPSACK_PRO_CI_NODE_TOTAL'] = '2'
1969
- end
1970
- after do
1971
- ENV.delete('KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN')
1972
- ENV.delete('KNAPSACK_PRO_CI_NODE_TOTAL')
1973
- end
1974
-
1975
- it 'splits slow test files by test examples AND ensures the test examples are executed only once' do
1976
- rspec_options = '--format d'
1977
-
1978
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
1979
- describe 'A_describe' do
1980
- it 'A1 test example' do
1981
- expect(1).to eq 1
1982
- end
1983
- it 'A2 test example' do
1984
- expect(1).to eq 1
1985
- end
1986
- end
1987
- SPEC
1988
-
1989
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
1990
- describe 'B_describe' do
1991
- it 'B1 test example' do
1992
- expect(1).to eq 1
1993
- end
1994
- it 'B2 test example' do
1995
- expect(1).to eq 1
1996
- end
1997
- end
1998
- SPEC
1999
-
2000
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
2001
- describe 'C_describe' do
2002
- it 'C1 test example' do
2003
- expect(1).to eq 1
2004
- end
2005
- it 'C2 test example' do
2006
- expect(1).to eq 1
2007
- end
2008
- end
2009
- SPEC
2010
-
2011
- generate_specs(spec_helper_with_knapsack, rspec_options, [
2012
- [spec_a, spec_b, spec_c]
2013
- ])
2014
- stub_test_cases_for_slow_test_files([
2015
- "#{spec_a.path}[1:1]",
2016
- "#{spec_a.path}[1:2]",
2017
- ])
2018
- stub_spec_batches([
2019
- ["#{spec_a.path}[1:1]", spec_b.path],
2020
- ["#{spec_a.path}[1:2]", spec_c.path],
2021
- ])
2022
-
2023
- actual = subject
2024
-
2025
- expect(actual.stdout).to include(
2026
- <<~OUTPUT
2027
- A_describe
2028
- A1 test example
2029
-
2030
- B_describe
2031
- B1 test example
2032
- B2 test example
2033
- OUTPUT
2034
- )
2035
-
2036
- expect(actual.stdout).to include(
2037
- <<~OUTPUT
2038
- A_describe
2039
- A2 test example
2040
-
2041
- C_describe
2042
- C1 test example
2043
- C2 test example
2044
- OUTPUT
2045
- )
2046
-
2047
- expect(actual.stdout.scan(/A1 test example/).size).to eq 1
2048
- expect(actual.stdout.scan(/A2 test example/).size).to eq 1
2049
-
2050
- expect(actual.stdout).to include('6 examples, 0 failures')
2051
-
2052
- expect(actual.exit_code).to eq 0
2053
- end
2054
- end
2055
-
2056
- context 'when the RSpec split by test examples is enabled AND --tag is set' do
2057
- before do
2058
- # Remember to stub the Queue API batches to include test examples (example: a_spec.rb[1:2])
2059
- # for the following slow test files.
2060
- ENV['KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN'] = "#{SPEC_DIRECTORY}/a_spec.rb"
2061
-
2062
- ENV['KNAPSACK_PRO_CI_NODE_TOTAL'] = '2'
2063
- end
2064
- after do
2065
- ENV.delete('KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN')
2066
- ENV.delete('KNAPSACK_PRO_CI_NODE_TOTAL')
2067
- end
2068
-
2069
- it 'splits slow test files by test examples AND ensures the test examples are executed only once' do
2070
- rspec_options = '--format d --tag my_tag'
2071
-
2072
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
2073
- describe 'A_describe' do
2074
- it 'A1 test example' do
2075
- expect(1).to eq 1
2076
- end
2077
- it 'A2 test example', :my_tag do
2078
- expect(1).to eq 1
2079
- end
2080
- end
2081
- SPEC
2082
-
2083
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
2084
- describe 'B_describe', :my_tag do
2085
- it 'B1 test example' do
2086
- expect(1).to eq 1
2087
- end
2088
- it 'B2 test example' do
2089
- expect(1).to eq 1
2090
- end
2091
- end
2092
- SPEC
2093
-
2094
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
2095
- describe 'C_describe' do
2096
- it 'C1 test example', :my_tag do
2097
- expect(1).to eq 1
2098
- end
2099
- it 'C2 test example' do
2100
- expect(1).to eq 1
2101
- end
2102
- end
2103
- SPEC
2104
-
2105
- generate_specs(spec_helper_with_knapsack, rspec_options, [
2106
- [spec_a, spec_b, spec_c]
2107
- ])
2108
- stub_test_cases_for_slow_test_files([
2109
- "#{spec_a.path}[1:2]", # only this test example is tagged
2110
- ])
2111
- stub_spec_batches([
2112
- [spec_b.path],
2113
- ["#{spec_a.path}[1:2]", spec_c.path],
2114
- ])
2115
-
2116
- actual = subject
2117
-
2118
- expect(actual.stdout).to_not include('A1 test example')
2119
- expect(actual.stdout).to include('A2 test example')
2120
- expect(actual.stdout).to include('B1 test example')
2121
- expect(actual.stdout).to include('B2 test example')
2122
- expect(actual.stdout).to include('C1 test example')
2123
- expect(actual.stdout).to_not include('C2 test example')
2124
-
2125
- expect(actual.stdout).to include('4 examples, 0 failures')
2126
-
2127
- expect(actual.exit_code).to eq 0
2128
- end
2129
- end
2130
-
2131
- context 'when the RSpec split by test examples is enabled AND JSON formatter is used' do
2132
- let(:json_file) { "#{SPEC_DIRECTORY}/rspec.json" }
2133
-
2134
- before do
2135
- # Remember to stub the Queue API batches to include test examples (example: a_spec.rb[1:1])
2136
- # for the following slow test files.
2137
- ENV['KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN'] = "#{SPEC_DIRECTORY}/a_spec.rb"
2138
-
2139
- ENV['KNAPSACK_PRO_CI_NODE_TOTAL'] = '2'
2140
- end
2141
- after do
2142
- ENV.delete('KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN')
2143
- ENV.delete('KNAPSACK_PRO_CI_NODE_TOTAL')
2144
- end
2145
-
2146
- it 'produces a JSON report' do
2147
- rspec_options = "--format documentation --format json --out ./#{json_file}"
2148
-
2149
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
2150
- describe 'A_describe' do
2151
- it 'A1 test example' do
2152
- expect(1).to eq 1
2153
- end
2154
- it 'A2 test example' do
2155
- expect(1).to eq 1
2156
- end
2157
- end
2158
- SPEC
2159
-
2160
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
2161
- describe 'B_describe' do
2162
- it 'B1 test example' do
2163
- expect(1).to eq 1
2164
- end
2165
- it 'B2 test example' do
2166
- expect(1).to eq 1
2167
- end
2168
- end
2169
- SPEC
2170
-
2171
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
2172
- describe 'C_describe' do
2173
- it 'C1 test example' do
2174
- expect(1).to eq 1
2175
- end
2176
- it 'C2 test example' do
2177
- expect(1).to eq 1
2178
- end
2179
- end
2180
- SPEC
2181
-
2182
- generate_specs(spec_helper_with_knapsack, rspec_options, [
2183
- [spec_a, spec_b, spec_c]
2184
- ])
2185
- stub_test_cases_for_slow_test_files([
2186
- "#{spec_a.path}[1:1]",
2187
- "#{spec_a.path}[1:2]",
2188
- ])
2189
- stub_spec_batches([
2190
- ["#{spec_a.path}[1:1]", spec_b.path],
2191
- ["#{spec_a.path}[1:2]", spec_c.path],
2192
- ])
2193
-
2194
- actual = subject
2195
-
2196
- file_content = File.read(json_file)
2197
- json = JSON.load(file_content)
2198
- examples = json.fetch('examples')
2199
-
2200
- example_ids = examples.map do
2201
- _1.fetch('id')
2202
- end
2203
- expect(example_ids).to match_array([
2204
- './spec_integration/a_spec.rb[1:1]',
2205
- './spec_integration/b_spec.rb[1:1]',
2206
- './spec_integration/b_spec.rb[1:2]',
2207
- './spec_integration/a_spec.rb[1:2]',
2208
- './spec_integration/c_spec.rb[1:1]',
2209
- './spec_integration/c_spec.rb[1:2]'
2210
- ])
2211
-
2212
- example_full_descriptions = examples.map do
2213
- _1.fetch('full_description')
2214
- end
2215
- expect(example_full_descriptions).to match_array([
2216
- 'A_describe A1 test example',
2217
- 'B_describe B1 test example',
2218
- 'B_describe B2 test example',
2219
- 'A_describe A2 test example',
2220
- 'C_describe C1 test example',
2221
- 'C_describe C2 test example'
2222
- ])
2223
-
2224
- expect(json.fetch('summary_line')).to eq '6 examples, 0 failures'
2225
-
2226
- expect(actual.exit_code).to eq 0
2227
- end
2228
- end
2229
-
2230
- context 'when the RSpec split by test examples is enabled AND JUnit XML formatter is used' do
2231
- let(:xml_file) { "#{SPEC_DIRECTORY}/rspec.xml" }
2232
-
2233
- before do
2234
- # Remember to stub the Queue API batches to include test examples (example: a_spec.rb[1:1])
2235
- # for the following slow test files.
2236
- ENV['KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN'] = "#{SPEC_DIRECTORY}/a_spec.rb"
2237
-
2238
- ENV['KNAPSACK_PRO_CI_NODE_TOTAL'] = '2'
2239
- end
2240
- after do
2241
- ENV.delete('KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN')
2242
- ENV.delete('KNAPSACK_PRO_CI_NODE_TOTAL')
2243
- end
2244
-
2245
- it 'produces a JUnit XML report' do
2246
- rspec_options = "--format documentation --format RspecJunitFormatter --out ./#{xml_file}"
2247
-
2248
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
2249
- describe 'A_describe' do
2250
- it 'A1 test example' do
2251
- expect(1).to eq 1
2252
- end
2253
- it 'A2 test example' do
2254
- expect(1).to eq 1
2255
- end
2256
- end
2257
- SPEC
2258
-
2259
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
2260
- describe 'B_describe' do
2261
- it 'B1 test example' do
2262
- expect(1).to eq 1
2263
- end
2264
- it 'B2 test example' do
2265
- expect(1).to eq 1
2266
- end
2267
- end
2268
- SPEC
2269
-
2270
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
2271
- describe 'C_describe' do
2272
- it 'C1 test example' do
2273
- expect(1).to eq 1
2274
- end
2275
- it 'C2 test example' do
2276
- expect(1).to eq 1
2277
- end
2278
- end
2279
- SPEC
2280
-
2281
- generate_specs(spec_helper_with_knapsack, rspec_options, [
2282
- [spec_a, spec_b, spec_c]
2283
- ])
2284
- stub_test_cases_for_slow_test_files([
2285
- "#{spec_a.path}[1:1]",
2286
- "#{spec_a.path}[1:2]",
2287
- ])
2288
- stub_spec_batches([
2289
- ["#{spec_a.path}[1:1]", spec_b.path],
2290
- ["#{spec_a.path}[1:2]", spec_c.path],
2291
- ])
2292
-
2293
- actual = subject
2294
-
2295
- file_content = File.read(xml_file)
2296
- doc = Nokogiri::XML(file_content)
2297
-
2298
- files = doc.xpath('//testcase').map do |testcase|
2299
- testcase['file']
2300
- end
2301
- expect(files).to eq([
2302
- './spec_integration/a_spec.rb',
2303
- './spec_integration/b_spec.rb',
2304
- './spec_integration/b_spec.rb',
2305
- './spec_integration/a_spec.rb',
2306
- './spec_integration/c_spec.rb',
2307
- './spec_integration/c_spec.rb',
2308
- ])
2309
-
2310
- examples = doc.xpath('//testcase').map do |testcase|
2311
- testcase['name']
2312
- end
2313
- expect(examples).to eq([
2314
- 'A_describe A1 test example',
2315
- 'B_describe B1 test example',
2316
- 'B_describe B2 test example',
2317
- 'A_describe A2 test example',
2318
- 'C_describe C1 test example',
2319
- 'C_describe C2 test example',
2320
- ])
2321
-
2322
- expect(actual.exit_code).to eq 0
2323
- end
2324
- end
2325
-
2326
- context 'when the RSpec split by test examples is enabled AND simplecov is used' do
2327
- let(:coverage_dir) { "#{KNAPSACK_PRO_TMP_DIR}/coverage" }
2328
- let(:coverage_file) { "#{coverage_dir}/index.html" }
2329
-
2330
- before do
2331
- # Remember to stub the Queue API batches to include test examples (example: a_spec.rb[1:1])
2332
- # for the following slow test files.
2333
- ENV['KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN'] = "#{SPEC_DIRECTORY}/a_spec.rb"
2334
-
2335
- ENV['KNAPSACK_PRO_CI_NODE_TOTAL'] = '2'
2336
- end
2337
- after do
2338
- ENV.delete('KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN')
2339
- ENV.delete('KNAPSACK_PRO_CI_NODE_TOTAL')
2340
- end
2341
-
2342
- it 'produces a code coverage report' do
2343
- rspec_options = '--format documentation'
2344
-
2345
- spec_helper = <<~SPEC
2346
- require 'knapsack_pro'
2347
- KnapsackPro::Adapters::RSpecAdapter.bind
2348
-
2349
- require 'simplecov'
2350
- SimpleCov.start do
2351
- coverage_dir '#{coverage_dir}'
2352
- end
2353
- SPEC
2354
-
2355
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
2356
- describe 'A_describe' do
2357
- it 'A1 test example' do
2358
- expect(1).to eq 1
2359
- end
2360
- it 'A2 test example' do
2361
- expect(1).to eq 1
2362
- end
2363
- end
2364
- SPEC
2365
-
2366
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
2367
- describe 'B_describe' do
2368
- it 'B1 test example' do
2369
- expect(1).to eq 1
2370
- end
2371
- it 'B2 test example' do
2372
- expect(1).to eq 1
2373
- end
2374
- end
2375
- SPEC
2376
-
2377
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
2378
- describe 'C_describe' do
2379
- it 'C1 test example' do
2380
- expect(1).to eq 1
2381
- end
2382
- it 'C2 test example' do
2383
- expect(1).to eq 1
2384
- end
2385
- end
2386
- SPEC
2387
-
2388
- generate_specs(spec_helper, rspec_options, [
2389
- [spec_a, spec_b, spec_c]
2390
- ])
2391
- stub_test_cases_for_slow_test_files([
2392
- "#{spec_a.path}[1:1]",
2393
- "#{spec_a.path}[1:2]",
2394
- ])
2395
- stub_spec_batches([
2396
- ["#{spec_a.path}[1:1]", spec_b.path],
2397
- ["#{spec_a.path}[1:2]", spec_c.path],
2398
- ])
2399
-
2400
- actual = subject
2401
-
2402
- file_content = File.read(coverage_file)
2403
-
2404
- expect(file_content).to include(spec_a.path)
2405
- expect(file_content).to include(spec_b.path)
2406
- expect(file_content).to include(spec_c.path)
2407
-
2408
- expect(actual.exit_code).to eq 0
2409
- end
2410
- end
2411
-
2412
- context 'when the RSpec split by test examples is enabled AND test files are split by test examples AND slow test files are not detected (for example, the user could have passed test examples like a_spec.rb[1:1] directly using KNAPSACK_PRO_TEST_FILE_LIST_SOURCE_FILE or KNAPSACK_PRO_TEST_FILE_LIST)' do
2413
- before do
2414
- ENV['KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES'] = 'true'
2415
- ENV['KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN'] = ""
2416
- ENV['KNAPSACK_PRO_CI_NODE_TOTAL'] = '2'
2417
- end
2418
- after do
2419
- ENV.delete('KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES')
2420
- ENV.delete('KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN')
2421
- ENV.delete('KNAPSACK_PRO_CI_NODE_TOTAL')
2422
- end
2423
-
2424
- it 'detects test execution times correctly for individual test examples even though they are not considered slow test files' do
2425
- ENV['TEST__LOG_EXECUTION_TIMES'] = 'true'
2426
- rspec_options = '--format d'
2427
-
2428
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
2429
- describe 'A_describe' do
2430
- it 'A1 test example' do
2431
- expect(1).to eq 1
2432
- end
2433
- it 'A2 test example' do
2434
- expect(1).to eq 1
2435
- end
2436
- end
2437
- SPEC
2438
-
2439
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
2440
- describe 'B_describe' do
2441
- it 'B1 test example' do
2442
- expect(1).to eq 1
2443
- end
2444
- it 'B2 test example' do
2445
- expect(1).to eq 1
2446
- end
2447
- end
2448
- SPEC
2449
-
2450
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
2451
- describe 'C_describe' do
2452
- it 'C1 test example' do
2453
- expect(1).to eq 1
2454
- end
2455
- it 'C2 test example' do
2456
- expect(1).to eq 1
2457
- end
2458
- end
2459
- SPEC
2460
-
2461
- generate_specs(spec_helper_with_knapsack, rspec_options, [
2462
- [spec_a, spec_b, spec_c]
2463
- ])
2464
- stub_test_cases_for_slow_test_files([
2465
- "#{spec_a.path}[1:1]",
2466
- "#{spec_a.path}[1:2]",
2467
- ])
2468
- stub_spec_batches([
2469
- ["#{spec_a.path}[1:1]", spec_b.path],
2470
- ["#{spec_a.path}[1:2]", spec_c.path],
2471
- ])
2472
-
2473
- actual = subject
2474
-
2475
- expect(actual.stdout).to include(
2476
- <<~OUTPUT
2477
- A_describe
2478
- A1 test example
2479
-
2480
- B_describe
2481
- B1 test example
2482
- B2 test example
2483
- OUTPUT
2484
- )
2485
-
2486
- expect(actual.stdout).to include(
2487
- <<~OUTPUT
2488
- A_describe
2489
- A2 test example
2490
-
2491
- C_describe
2492
- C1 test example
2493
- C2 test example
2494
- OUTPUT
2495
- )
2496
-
2497
- expect(actual.stdout.scan(/A1 test example/).size).to eq 1
2498
- expect(actual.stdout.scan(/A2 test example/).size).to eq 1
2499
-
2500
- expect(actual.stdout).to include('6 examples, 0 failures')
2501
-
2502
- expect(actual.stdout).to include('[INTEGRATION TEST] test_files: 4, test files have execution time: true')
2503
-
2504
- expect(actual.exit_code).to eq 0
2505
- end
2506
- end
2507
-
2508
- context 'when the example_status_persistence_file_path option is used and multiple batches of tests are fetched from the Queue API and some tests are pending and failing' do
2509
- let(:examples_file_path) { "#{SPEC_DIRECTORY}/examples.txt" }
2510
-
2511
- after do
2512
- File.delete(examples_file_path) if File.exist?(examples_file_path)
2513
- end
2514
-
2515
- it 'runs tests AND creates the example status persistence file' do
2516
- rspec_options = '--format d'
2517
-
2518
- spec_helper = <<~SPEC
2519
- require 'knapsack_pro'
2520
- KnapsackPro::Adapters::RSpecAdapter.bind
2521
-
2522
- RSpec.configure do |config|
2523
- config.example_status_persistence_file_path = '#{examples_file_path}'
2524
- end
2525
- SPEC
2526
-
2527
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
2528
- describe 'A_describe' do
2529
- xit 'A1 test example' do
2530
- expect(1).to eq 1
2531
- end
2532
- end
2533
- SPEC
2534
-
2535
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
2536
- describe 'B_describe' do
2537
- it 'B1 test example' do
2538
- expect(1).to eq 0
2539
- end
2540
- end
2541
- SPEC
2542
-
2543
- spec_c = Spec.new('c_spec.rb', <<~SPEC)
2544
- describe 'C_describe' do
2545
- it 'C1 test example' do
2546
- expect(1).to eq 1
2547
- end
2548
- it 'C2 test example' do
2549
- expect(1).to eq 0
2550
- end
2551
- end
2552
- SPEC
2553
-
2554
- generate_specs(spec_helper, rspec_options, [
2555
- [spec_a, spec_b],
2556
- [spec_c],
2557
- ])
2558
-
2559
- actual = subject
2560
-
2561
- expect(actual.stdout).to include('4 examples, 2 failures, 1 pending')
2562
-
2563
- expect(File.exist?(examples_file_path)).to be true
2564
-
2565
- examples_file_content = File.read(examples_file_path)
2566
-
2567
- expect(examples_file_content).to include './spec_integration/a_spec.rb[1:1] | pending'
2568
- expect(examples_file_content).to include './spec_integration/b_spec.rb[1:1] | failed'
2569
- expect(examples_file_content).to include './spec_integration/c_spec.rb[1:1] | passed'
2570
- expect(examples_file_content).to include './spec_integration/c_spec.rb[1:2] | failed'
2571
-
2572
- expect(actual.exit_code).to eq 1
2573
- end
2574
- end
2575
-
2576
- context 'when the .rspec file has RSpec options' do
2577
- let(:dot_rspec_file) { "#{SPEC_DIRECTORY}/.rspec" }
2578
-
2579
- it 'ignores options from the .rspec file' do
2580
- File.open(dot_rspec_file, 'w') { |file| file.write('--format documentation') }
2581
-
2582
- rspec_options = ''
2583
-
2584
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
2585
- describe 'A_describe' do
2586
- it 'A1 test example' do
2587
- expect(1).to eq 1
2588
- end
2589
- end
2590
- SPEC
2591
-
2592
- generate_specs(spec_helper_with_knapsack, rspec_options, [
2593
- [spec_a],
2594
- ])
2595
-
2596
- actual = subject
2597
-
2598
- expect(actual.stdout).not_to include('A1 test example')
2599
-
2600
- expect(actual.stdout).to include('1 example, 0 failures')
2601
-
2602
- expect(actual.exit_code).to eq 0
2603
- end
2604
- end
2605
-
2606
- context 'when --options is set' do
2607
- let(:rspec_custom_options_file) { "#{SPEC_DIRECTORY}/.rspec_custom_options" }
2608
-
2609
- it 'uses options from the custom rspec file' do
2610
- rspec_custom_options = <<~FILE
2611
- --require spec_helper
2612
- --profile
2613
- FILE
2614
- File.open(rspec_custom_options_file, 'w') { |file| file.write(rspec_custom_options) }
2615
-
2616
- rspec_options = "--options ./#{rspec_custom_options_file}"
2617
-
2618
- spec_a = Spec.new('a_spec.rb', <<~SPEC)
2619
- describe 'A_describe' do
2620
- it 'A1 test example' do
2621
- expect(1).to eq 1
2622
- end
2623
- end
2624
- SPEC
2625
-
2626
- spec_b = Spec.new('b_spec.rb', <<~SPEC)
2627
- describe 'B_describe' do
2628
- it 'B1 test example' do
2629
- expect(1).to eq 1
2630
- end
2631
- end
2632
- SPEC
2633
-
2634
- generate_specs(spec_helper_with_knapsack, rspec_options, [
2635
- [spec_a],
2636
- [spec_b],
2637
- ])
2638
-
2639
- actual = subject
2640
-
2641
- expect(actual.stdout).to include('2 examples, 0 failures')
2642
-
2643
- expect(actual.stdout).to include('Top 2 slowest example groups')
2644
-
2645
- expect(actual.exit_code).to eq 0
2646
- end
2647
- end
2648
-
2649
- context 'when rspec is run without knapsack_pro' do
2650
- let(:spec) { Spec.new('a_spec.rb', <<~SPEC) }
2651
- require_relative "spec_helper.rb"
2652
-
2653
- describe 'A_describe' do
2654
- it 'A1 test example' do
2655
- expect(1).to eq 1
2656
- end
2657
- end
2658
- SPEC
2659
-
2660
- let(:command) { "bundle exec rspec #{spec.path}" }
2661
-
2662
- it 'runs successfully' do
2663
- generate_spec_helper(spec_helper_with_knapsack)
2664
- generate_spec_files([spec])
2665
-
2666
- actual = subject
2667
-
2668
- expect(actual.stdout).to include('1 example, 0 failures')
2669
- expect(actual.exit_code).to eq 0
2670
- end
2671
- end
2672
- end