knapsack_pro 5.6.0 → 5.7.0

Sign up to get free protection for your applications and to get access to all the features.
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