knapsack_pro 5.6.0 → 5.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fa2ae33f8d962bbd8d5f1639e050f2a43e9ad28bf655d637d43ca2c23bc1d7d3
4
- data.tar.gz: 70e747f428235b65bba04ed2f748221170a6971e8982e0ab0fbbdb60177d9a94
3
+ metadata.gz: 87b8a5c7eb2a78f487c9029cdeda3a1cc367b15e248eb1f3b5aaaf1959ebe333
4
+ data.tar.gz: 12fef31bb8aac248014b3d808190f7f2e7ae6217e83e4af9e40b17b6f98ed379
5
5
  SHA512:
6
- metadata.gz: ed58c0b63af2f3301e7233c142da4165a9c2c9a4f31987d465a803d3b4fdab590137d2ef71bbf6b80b9abc95f513cea605091b5caa7fcd0598620790977cc29b
7
- data.tar.gz: 607af355f302481ca595f577428ea49565e711a790c284d7fb595f0f15106070a99e85acf4ebd5cf0e073e672ee37f9d851eb2b464c372dca550bf5c878c8050
6
+ metadata.gz: 43379ac46ef1c5fa6a3fccf0d598831e009564ba37bdb264c681799aa893d5a9d8fbb569ce2bd83fe297b9c885117e95a5439731fd16ea35aa2f294acb88d936
7
+ data.tar.gz: 1be1143ac276347a0dee92bb15b7660f36b666c9cb8d025e9b1931f463803f9efc2a38ced34d4ca27bbfaa466fc1b6afc71d2960ced12b09888ca09a6572b14b
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ### 5.7.0
4
+
5
+ * Performance improvement: don't run `rake knapsack_pro:rspec_test_example_detector` when no slow test files are detected for RSpec.
6
+
7
+ https://github.com/KnapsackPro/knapsack_pro-ruby/pull/225
8
+
9
+ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v5.6.0...v5.7.0
10
+
3
11
  ### 5.6.0
4
12
 
5
13
  * Use `frozen_string_literal: true` to reduce memory usage
@@ -11,6 +11,14 @@ module KnapsackPro
11
11
  "#{KnapsackPro::Config::TempFiles::TEMP_DIRECTORY_PATH}/#{adapter_name}-bind_method_called_for_node_#{KnapsackPro::Config::Env.ci_node_index}.txt"
12
12
  end
13
13
 
14
+ def self.split_by_test_cases_enabled?
15
+ false
16
+ end
17
+
18
+ def self.test_file_cases_for(slow_test_files)
19
+ raise NotImplementedError
20
+ end
21
+
14
22
  def self.slow_test_file?(adapter_class, test_file_path)
15
23
  @slow_test_file_paths ||=
16
24
  begin
@@ -5,6 +5,35 @@ module KnapsackPro
5
5
  class RSpecAdapter < BaseAdapter
6
6
  TEST_DIR_PATTERN = 'spec/**{,/*/**}/*_spec.rb'
7
7
 
8
+ def self.split_by_test_cases_enabled?
9
+ return false unless KnapsackPro::Config::Env.rspec_split_by_test_examples?
10
+
11
+ require 'rspec/core/version'
12
+ unless Gem::Version.new(::RSpec::Core::Version::STRING) >= Gem::Version.new('3.3.0')
13
+ raise "RSpec >= 3.3.0 is required to split test files by test examples. Learn more: #{KnapsackPro::Urls::SPLIT_BY_TEST_EXAMPLES}"
14
+ end
15
+
16
+ true
17
+ end
18
+
19
+ def self.test_file_cases_for(slow_test_files)
20
+ KnapsackPro.logger.info("Generating RSpec test examples JSON report for slow test files to prepare it to be split by test examples (by individual test cases). Thanks to that, a single slow test file can be split across parallel CI nodes. Analyzing #{slow_test_files.size} slow test files.")
21
+
22
+ # generate the RSpec JSON report in a separate process to not pollute the RSpec state
23
+ cmd = [
24
+ 'RACK_ENV=test',
25
+ 'RAILS_ENV=test',
26
+ KnapsackPro::Config::Env.rspec_test_example_detector_prefix,
27
+ 'rake knapsack_pro:rspec_test_example_detector',
28
+ ].join(' ')
29
+ unless Kernel.system(cmd)
30
+ raise "Could not generate JSON report for RSpec. Rake task failed when running #{cmd}"
31
+ end
32
+
33
+ # read the JSON report
34
+ KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector.new.test_file_example_paths
35
+ end
36
+
8
37
  def self.ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!(cli_args)
9
38
  if KnapsackPro::Config::Env.rspec_split_by_test_examples? && has_tag_option?(cli_args)
10
39
  error_message = "It is not allowed to use the RSpec tag option together with the RSpec split by test examples feature. Please see: #{KnapsackPro::Urls::RSPEC__SPLIT_BY_TEST_EXAMPLES__TAG}"
@@ -35,35 +35,16 @@ module KnapsackPro
35
35
  def fast_and_slow_test_files_to_run
36
36
  test_files_to_run = all_test_files_to_run
37
37
 
38
- if adapter_class == KnapsackPro::Adapters::RSpecAdapter && KnapsackPro::Config::Env.rspec_split_by_test_examples?
39
- require 'rspec/core/version'
40
- unless Gem::Version.new(::RSpec::Core::Version::STRING) >= Gem::Version.new('3.3.0')
41
- raise "RSpec >= 3.3.0 is required to split test files by test examples. Learn more: #{KnapsackPro::Urls::SPLIT_BY_TEST_EXAMPLES}"
42
- end
43
-
38
+ if adapter_class.split_by_test_cases_enabled?
44
39
  slow_test_files = get_slow_test_files
40
+ return test_files_to_run if slow_test_files.empty?
45
41
 
46
- KnapsackPro.logger.info("Generating RSpec test examples JSON report for slow test files to prepare it to be split by test examples (by individual 'it's. Thanks to that a single slow test file can be split across parallel CI nodes). Analyzing #{slow_test_files.size} slow test files.")
47
-
48
- # generate RSpec JSON report in separate process to not pollute RSpec state
49
- cmd = [
50
- 'RACK_ENV=test',
51
- 'RAILS_ENV=test',
52
- KnapsackPro::Config::Env.rspec_test_example_detector_prefix,
53
- 'rake knapsack_pro:rspec_test_example_detector',
54
- ].join(' ')
55
- unless Kernel.system(cmd)
56
- raise "Could not generate JSON report for RSpec. Rake task failed when running #{cmd}"
57
- end
42
+ test_file_cases = adapter_class.test_file_cases_for(slow_test_files)
58
43
 
59
- # read JSON report
60
- detector = KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector.new
61
- test_file_example_paths = detector.test_file_example_paths
62
-
63
- KnapsackPro::TestFilesWithTestCasesComposer.call(test_files_to_run, slow_test_files, test_file_example_paths)
64
- else
65
- test_files_to_run
44
+ return KnapsackPro::TestFilesWithTestCasesComposer.call(test_files_to_run, slow_test_files, test_file_cases)
66
45
  end
46
+
47
+ test_files_to_run
67
48
  end
68
49
 
69
50
  private
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module KnapsackPro
4
- VERSION = '5.6.0'
4
+ VERSION = '5.7.0'
5
5
  end
@@ -42,6 +42,18 @@ describe KnapsackPro::Adapters::BaseAdapter do
42
42
  end
43
43
  end
44
44
 
45
+ describe '.split_by_test_cases_enabled?' do
46
+ subject { described_class.split_by_test_cases_enabled? }
47
+
48
+ it { expect(subject).to be false }
49
+ end
50
+
51
+ describe '.test_file_cases_for' do
52
+ subject { described_class.test_file_cases_for([]) }
53
+
54
+ it { expect { subject }.to raise_error NotImplementedError }
55
+ end
56
+
45
57
  describe '.slow_test_file?' do
46
58
  let(:adapter_class) { double }
47
59
  let(:slow_test_files) do
@@ -12,6 +12,81 @@ describe KnapsackPro::Adapters::RSpecAdapter do
12
12
  it_behaves_like 'adapter'
13
13
  end
14
14
 
15
+ describe '.split_by_test_cases_enabled?' do
16
+ subject { described_class.split_by_test_cases_enabled? }
17
+
18
+ before do
19
+ expect(KnapsackPro::Config::Env).to receive(:rspec_split_by_test_examples?).and_return(rspec_split_by_test_examples_enabled)
20
+ end
21
+
22
+ context 'when the RSpec split by test examples is enabled' do
23
+ let(:rspec_split_by_test_examples_enabled) { true }
24
+
25
+ it { expect(subject).to be true }
26
+
27
+ context 'when the RSpec version is < 3.3.0' do
28
+ before do
29
+ stub_const('RSpec::Core::Version::STRING', '3.2.0')
30
+ end
31
+
32
+ it do
33
+ expect { subject }.to raise_error RuntimeError, 'RSpec >= 3.3.0 is required to split test files by test examples. Learn more: https://knapsackpro.com/perma/ruby/split-by-test-examples'
34
+ end
35
+ end
36
+ end
37
+
38
+ context 'when the RSpec split by test examples is disabled' do
39
+ let(:rspec_split_by_test_examples_enabled) { false }
40
+
41
+ it { expect(subject).to be false }
42
+ end
43
+ end
44
+
45
+ describe '.test_file_cases_for' do
46
+ let(:slow_test_files) do
47
+ [
48
+ '1_spec.rb',
49
+ '2_spec.rb',
50
+ '3_spec.rb',
51
+ '4_spec.rb',
52
+ '5_spec.rb',
53
+ ]
54
+ end
55
+
56
+ subject { described_class.test_file_cases_for(slow_test_files) }
57
+
58
+ before do
59
+ logger = instance_double(Logger)
60
+ expect(KnapsackPro).to receive(:logger).and_return(logger)
61
+ expect(logger).to receive(:info).with("Generating RSpec test examples JSON report for slow test files to prepare it to be split by test examples (by individual test cases). Thanks to that, a single slow test file can be split across parallel CI nodes. Analyzing 5 slow test files.")
62
+
63
+ cmd = 'RACK_ENV=test RAILS_ENV=test bundle exec rake knapsack_pro:rspec_test_example_detector'
64
+ expect(Kernel).to receive(:system).with(cmd).and_return(cmd_result)
65
+ end
66
+
67
+ context 'when the rake task to detect RSpec test examples succeeded' do
68
+ let(:cmd_result) { true }
69
+
70
+ it 'returns test example paths for slow test files' do
71
+ rspec_test_example_detector = instance_double(KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector)
72
+ expect(KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector).to receive(:new).and_return(rspec_test_example_detector)
73
+
74
+ test_file_example_paths = double
75
+ expect(rspec_test_example_detector).to receive(:test_file_example_paths).and_return(test_file_example_paths)
76
+
77
+ expect(subject).to eq test_file_example_paths
78
+ end
79
+ end
80
+
81
+ context 'when the rake task to detect RSpec test examples failed' do
82
+ let(:cmd_result) { false }
83
+
84
+ it do
85
+ expect { subject }.to raise_error(RuntimeError, 'Could not generate JSON report for RSpec. Rake task failed when running RACK_ENV=test RAILS_ENV=test bundle exec rake knapsack_pro:rspec_test_example_detector')
86
+ end
87
+ end
88
+ end
89
+
15
90
  describe '.ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!' do
16
91
  let(:cli_args) { double }
17
92
 
@@ -117,8 +117,8 @@ describe KnapsackPro::BaseAllocatorBuilder do
117
117
  describe '#fast_and_slow_test_files_to_run' do
118
118
  subject { allocator_builder.fast_and_slow_test_files_to_run }
119
119
 
120
- context 'when looking for test files on disk by default' do
121
- it do
120
+ context 'when split by test cases disabled' do
121
+ it 'returns test files to run based on test files on the disk' do
122
122
  test_file_pattern = double
123
123
  expect(KnapsackPro::TestFilePattern).to receive(:call).with(adapter_class).and_return(test_file_pattern)
124
124
 
@@ -129,70 +129,44 @@ describe KnapsackPro::BaseAllocatorBuilder do
129
129
  end
130
130
  end
131
131
 
132
- context 'when RSpec adapter AND rspec split by test examples is enabled' do
133
- let(:adapter_class) { KnapsackPro::Adapters::RSpecAdapter }
132
+ context 'when split by test cases enabled' do
134
133
  let(:test_files_to_run) { double }
135
- let(:cmd) { 'RACK_ENV=test RAILS_ENV=test bundle exec rake knapsack_pro:rspec_test_example_detector' }
136
134
 
137
- before do
138
- expect(KnapsackPro::Config::Env).to receive(:rspec_split_by_test_examples?).and_return(true)
135
+ before do
136
+ expect(adapter_class).to receive(:split_by_test_cases_enabled?).and_return(true)
139
137
 
140
138
  test_file_pattern = double
141
139
  expect(KnapsackPro::TestFilePattern).to receive(:call).with(adapter_class).and_return(test_file_pattern)
142
140
 
143
141
  expect(KnapsackPro::TestFileFinder).to receive(:call).with(test_file_pattern).and_return(test_files_to_run)
144
- end
145
142
 
146
- context 'when RSpec version < 3.3.0' do
147
- before do
148
- stub_const('RSpec::Core::Version::STRING', '3.2.0')
149
- end
150
-
151
- it do
152
- expect { subject }.to raise_error RuntimeError, 'RSpec >= 3.3.0 is required to split test files by test examples. Learn more: https://knapsackpro.com/perma/ruby/split-by-test-examples'
153
- end
143
+ expect(allocator_builder).to receive(:get_slow_test_files).and_return(slow_test_files)
154
144
  end
155
145
 
156
- context 'when rake task to detect RSpec test examples works' do
157
- let(:slow_test_files) { double(size: 5) }
158
- let(:cmd_result) { true }
159
- let(:test_file_example_paths) { double }
160
- let(:logger) { instance_double(Logger) }
161
- let(:test_files_with_test_cases) { double }
162
-
163
- before do
164
- expect(allocator_builder).to receive(:get_slow_test_files).and_return(slow_test_files)
165
-
166
- expect(KnapsackPro).to receive(:logger).and_return(logger)
167
-
168
- expect(Kernel).to receive(:system).with(cmd).and_return(cmd_result)
169
-
170
- rspec_test_example_detector = instance_double(KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector)
171
- expect(KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector).to receive(:new).and_return(rspec_test_example_detector)
172
- expect(rspec_test_example_detector).to receive(:test_file_example_paths).and_return(test_file_example_paths)
173
-
174
- expect(KnapsackPro::TestFilesWithTestCasesComposer).to receive(:call).with(test_files_to_run, slow_test_files, test_file_example_paths).and_return(test_files_with_test_cases)
146
+ context 'when slow test files are detected' do
147
+ let(:slow_test_files) do
148
+ [
149
+ '1_spec.rb',
150
+ '2_spec.rb',
151
+ ]
175
152
  end
176
153
 
177
- it do
178
- expect(logger).to receive(:info).with("Generating RSpec test examples JSON report for slow test files to prepare it to be split by test examples (by individual 'it's. Thanks to that a single slow test file can be split across parallel CI nodes). Analyzing 5 slow test files.")
154
+ it 'returns test files with test cases' do
155
+ test_file_cases = double
156
+ expect(adapter_class).to receive(:test_file_cases_for).with(slow_test_files).and_return(test_file_cases)
157
+
158
+ test_files_with_test_cases = double
159
+ expect(KnapsackPro::TestFilesWithTestCasesComposer).to receive(:call).with(test_files_to_run, slow_test_files, test_file_cases).and_return(test_files_with_test_cases)
179
160
 
180
161
  expect(subject).to eq test_files_with_test_cases
181
162
  end
182
163
  end
183
164
 
184
- context 'when rake task to detect RSpec test examples failed' do
185
- let(:slow_test_files) { double(size: 5) }
186
- let(:cmd_result) { false }
187
-
188
- before do
189
- expect(allocator_builder).to receive(:get_slow_test_files).and_return(slow_test_files)
190
-
191
- expect(Kernel).to receive(:system).with(cmd).and_return(cmd_result)
192
- end
165
+ context 'when slow test files are not detected' do
166
+ let(:slow_test_files) { [] }
193
167
 
194
- it do
195
- expect { subject }.to raise_error(RuntimeError, 'Could not generate JSON report for RSpec. Rake task failed when running RACK_ENV=test RAILS_ENV=test bundle exec rake knapsack_pro:rspec_test_example_detector')
168
+ it 'returns test files without test cases' do
169
+ expect(subject).to eq test_files_to_run
196
170
  end
197
171
  end
198
172
  end
@@ -282,15 +282,17 @@ describe KnapsackPro::Client::Connection do
282
282
  request_hash: request_hash)
283
283
  end
284
284
  let(:test_suite_token) { '3fa64859337f6e56409d49f865d13fd7' }
285
-
286
285
  let(:connection) { described_class.new(action) }
287
-
288
- before do
289
- stub_const('ENV', {
286
+ let(:headers) do
287
+ {
290
288
  'KNAPSACK_PRO_ENDPOINT' => 'http://api.knapsackpro.test:3000',
291
289
  'KNAPSACK_PRO_TEST_SUITE_TOKEN' => test_suite_token,
292
290
  'GITHUB_ACTIONS' => 'true',
293
- })
291
+ }
292
+ end
293
+
294
+ before do
295
+ stub_const('ENV', headers)
294
296
  end
295
297
 
296
298
  describe '#call' do
@@ -311,7 +313,7 @@ describe KnapsackPro::Client::Connection do
311
313
  expect(http).to receive(:read_timeout=).with(15)
312
314
  end
313
315
 
314
- context 'when http method is POST' do
316
+ context 'when http method is POST on GitHub Actions' do
315
317
  let(:http_method) { :post }
316
318
 
317
319
  before do
@@ -334,7 +336,30 @@ describe KnapsackPro::Client::Connection do
334
336
  end
335
337
  end
336
338
 
337
- context 'when http method is GET' do
339
+ context 'when http method is POST and CI is undetected' do
340
+ let(:http_method) { :post }
341
+
342
+ let(:headers) do
343
+ {
344
+ 'KNAPSACK_PRO_ENDPOINT' => 'http://api.knapsackpro.test:3000',
345
+ 'KNAPSACK_PRO_TEST_SUITE_TOKEN' => test_suite_token,
346
+ }
347
+ end
348
+
349
+ before do
350
+ expect(http).to receive(:post).with(
351
+ anything,
352
+ anything,
353
+ hash_not_including('KNAPSACK-PRO-CI-PROVIDER')
354
+ ).and_return(http_response)
355
+ end
356
+
357
+ it_behaves_like 'when request got response from API' do
358
+ let(:expected_http_method) { 'POST' }
359
+ end
360
+ end
361
+
362
+ context 'when http method is GET on GitHub Actions' do
338
363
  let(:http_method) { :get }
339
364
 
340
365
  before do
@@ -358,6 +383,28 @@ describe KnapsackPro::Client::Connection do
358
383
  end
359
384
  end
360
385
 
386
+ context 'when http method is GET and CI is undetected' do
387
+ let(:http_method) { :get }
388
+
389
+ let(:headers) do
390
+ {
391
+ 'KNAPSACK_PRO_ENDPOINT' => 'http://api.knapsackpro.test:3000',
392
+ 'KNAPSACK_PRO_TEST_SUITE_TOKEN' => test_suite_token,
393
+ }
394
+ end
395
+
396
+ before do
397
+ expect(http).to receive(:get).with(
398
+ anything,
399
+ hash_not_including('KNAPSACK-PRO-CI-PROVIDER')
400
+ ).and_return(http_response)
401
+ end
402
+
403
+ it_behaves_like 'when request got response from API' do
404
+ let(:expected_http_method) { 'GET' }
405
+ end
406
+ end
407
+
361
408
  context 'when retry request for http method POST' do
362
409
  let(:http_method) { :post }
363
410
 
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.6.0
4
+ version: 5.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ArturT
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-24 00:00:00.000000000 Z
11
+ date: 2023-09-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake