knapsack_pro 2.10.0 → 2.14.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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +40 -0
  3. data/README.md +31 -1562
  4. data/lib/knapsack_pro/adapters/base_adapter.rb +22 -0
  5. data/lib/knapsack_pro/adapters/rspec_adapter.rb +6 -2
  6. data/lib/knapsack_pro/allocator.rb +1 -1
  7. data/lib/knapsack_pro/base_allocator_builder.rb +0 -8
  8. data/lib/knapsack_pro/config/env.rb +1 -0
  9. data/lib/knapsack_pro/queue_allocator.rb +9 -20
  10. data/lib/knapsack_pro/queue_allocator_builder.rb +2 -2
  11. data/lib/knapsack_pro/report.rb +1 -1
  12. data/lib/knapsack_pro/runners/cucumber_runner.rb +4 -1
  13. data/lib/knapsack_pro/runners/minitest_runner.rb +4 -1
  14. data/lib/knapsack_pro/runners/queue/cucumber_runner.rb +4 -0
  15. data/lib/knapsack_pro/runners/queue/minitest_runner.rb +4 -0
  16. data/lib/knapsack_pro/runners/queue/rspec_runner.rb +2 -0
  17. data/lib/knapsack_pro/runners/rspec_runner.rb +4 -1
  18. data/lib/knapsack_pro/runners/spinach_runner.rb +4 -1
  19. data/lib/knapsack_pro/runners/test_unit_runner.rb +4 -1
  20. data/lib/knapsack_pro/slow_test_file_determiner.rb +1 -1
  21. data/lib/knapsack_pro/test_case_detectors/rspec_test_example_detector.rb +1 -1
  22. data/lib/knapsack_pro/tracker.rb +10 -6
  23. data/lib/knapsack_pro/version.rb +1 -1
  24. data/spec/knapsack_pro/adapters/base_adapter_spec.rb +51 -0
  25. data/spec/knapsack_pro/adapters/rspec_adapter_spec.rb +15 -9
  26. data/spec/knapsack_pro/queue_allocator_builder_spec.rb +6 -6
  27. data/spec/knapsack_pro/queue_allocator_spec.rb +33 -71
  28. data/spec/knapsack_pro/runners/cucumber_runner_spec.rb +2 -0
  29. data/spec/knapsack_pro/runners/minitest_runner_spec.rb +4 -0
  30. data/spec/knapsack_pro/runners/queue/cucumber_runner_spec.rb +27 -7
  31. data/spec/knapsack_pro/runners/queue/minitest_runner_spec.rb +27 -7
  32. data/spec/knapsack_pro/runners/queue/rspec_runner_spec.rb +2 -0
  33. data/spec/knapsack_pro/runners/rspec_runner_spec.rb +2 -0
  34. data/spec/knapsack_pro/runners/spinach_runner_spec.rb +2 -0
  35. data/spec/knapsack_pro/runners/test_unit_runner_spec.rb +2 -0
  36. data/spec/knapsack_pro/tracker_spec.rb +7 -3
  37. metadata +5 -5
@@ -8,11 +8,11 @@ describe KnapsackPro::QueueAllocatorBuilder do
8
8
  subject { allocator_builder.allocator }
9
9
 
10
10
  before do
11
- lazy_fast_and_slow_test_files_to_run = double
12
- expect(allocator_builder).to receive(:lazy_fast_and_slow_test_files_to_run).and_return(lazy_fast_and_slow_test_files_to_run)
11
+ fast_and_slow_test_files_to_run = double
12
+ expect(allocator_builder).to receive(:fast_and_slow_test_files_to_run).and_return(fast_and_slow_test_files_to_run)
13
13
 
14
- lazy_fallback_mode_test_files = double
15
- expect(allocator_builder).to receive(:lazy_fallback_mode_test_files).and_return(lazy_fallback_mode_test_files)
14
+ fallback_mode_test_files = double
15
+ expect(allocator_builder).to receive(:fallback_mode_test_files).and_return(fallback_mode_test_files)
16
16
 
17
17
  repository_adapter = double
18
18
  expect(KnapsackPro::RepositoryAdapterInitiator).to receive(:call).and_return(repository_adapter)
@@ -25,8 +25,8 @@ describe KnapsackPro::QueueAllocatorBuilder do
25
25
  expect(KnapsackPro::Config::Env).to receive(:ci_node_build_id).and_return(ci_node_build_id)
26
26
 
27
27
  expect(KnapsackPro::QueueAllocator).to receive(:new).with(
28
- lazy_fast_and_slow_test_files_to_run: lazy_fast_and_slow_test_files_to_run,
29
- lazy_fallback_mode_test_files: lazy_fallback_mode_test_files,
28
+ fast_and_slow_test_files_to_run: fast_and_slow_test_files_to_run,
29
+ fallback_mode_test_files: fallback_mode_test_files,
30
30
  ci_node_total: ci_node_total,
31
31
  ci_node_index: ci_node_index,
32
32
  ci_node_build_id: ci_node_build_id,
@@ -1,8 +1,6 @@
1
1
  describe KnapsackPro::QueueAllocator do
2
- let(:lazy_loaded_fast_and_slow_test_files_to_run) { double }
3
- let(:lazy_fast_and_slow_test_files_to_run) { double(call: lazy_loaded_fast_and_slow_test_files_to_run) }
4
- let(:lazy_loaded_fallback_mode_test_files) { double }
5
- let(:lazy_fallback_mode_test_files) { double(call: lazy_loaded_fallback_mode_test_files) }
2
+ let(:fast_and_slow_test_files_to_run) { double }
3
+ let(:fallback_mode_test_files) { double }
6
4
  let(:ci_node_total) { double }
7
5
  let(:ci_node_index) { double }
8
6
  let(:ci_node_build_id) { double }
@@ -10,8 +8,8 @@ describe KnapsackPro::QueueAllocator do
10
8
 
11
9
  let(:queue_allocator) do
12
10
  described_class.new(
13
- lazy_fast_and_slow_test_files_to_run: lazy_fast_and_slow_test_files_to_run,
14
- lazy_fallback_mode_test_files: lazy_fallback_mode_test_files,
11
+ fast_and_slow_test_files_to_run: fast_and_slow_test_files_to_run,
12
+ fallback_mode_test_files: fallback_mode_test_files,
15
13
  ci_node_total: ci_node_total,
16
14
  ci_node_index: ci_node_index,
17
15
  ci_node_build_id: ci_node_build_id,
@@ -66,7 +64,7 @@ describe KnapsackPro::QueueAllocator do
66
64
  context 'when fallback mode started' do
67
65
  before do
68
66
  test_flat_distributor = instance_double(KnapsackPro::TestFlatDistributor)
69
- expect(KnapsackPro::TestFlatDistributor).to receive(:new).with(lazy_loaded_fallback_mode_test_files, ci_node_total).and_return(test_flat_distributor)
67
+ expect(KnapsackPro::TestFlatDistributor).to receive(:new).with(fallback_mode_test_files, ci_node_total).and_return(test_flat_distributor)
70
68
  expect(test_flat_distributor).to receive(:test_files_for_node).with(ci_node_index).and_return([
71
69
  { 'path' => 'c_spec.rb' },
72
70
  { 'path' => 'd_spec.rb' },
@@ -133,32 +131,20 @@ describe KnapsackPro::QueueAllocator do
133
131
  let(:errors?) { false }
134
132
 
135
133
  context 'when response returns test files (successful attempt to connect to queue already existing on the API side)' do
136
- let(:test_files) do
137
- [
138
- { 'path' => 'a_spec.rb' },
139
- { 'path' => 'b_spec.rb' },
140
- ]
141
- end
142
134
  let(:response) do
143
- { 'test_files' => test_files }
135
+ {
136
+ 'test_files' => [
137
+ { 'path' => 'a_spec.rb' },
138
+ { 'path' => 'b_spec.rb' },
139
+ ]
140
+ }
144
141
  end
145
142
 
146
- context 'when test files encryption is enabled' do
147
- before do
148
- expect(KnapsackPro::Config::Env).to receive(:test_files_encrypted?).and_return(true)
149
- expect(KnapsackPro::Crypto::Decryptor).to receive(:call).with(lazy_loaded_fast_and_slow_test_files_to_run, response['test_files']).and_return(test_files)
150
- end
151
-
152
- it { should eq ['a_spec.rb', 'b_spec.rb'] }
143
+ before do
144
+ expect(KnapsackPro::Crypto::Decryptor).to receive(:call).with(fast_and_slow_test_files_to_run, response['test_files']).and_call_original
153
145
  end
154
146
 
155
- context 'when test files encryption is disabled' do
156
- before do
157
- expect(KnapsackPro::Config::Env).to receive(:test_files_encrypted?).and_return(false)
158
- end
159
-
160
- it { should eq ['a_spec.rb', 'b_spec.rb'] }
161
- end
147
+ it { should eq ['a_spec.rb', 'b_spec.rb'] }
162
148
  end
163
149
 
164
150
  context 'when response has code=ATTEMPT_CONNECT_TO_QUEUE_FAILED' do
@@ -172,7 +158,7 @@ describe KnapsackPro::QueueAllocator do
172
158
  expect(KnapsackPro::Crypto::BranchEncryptor).to receive(:call).with(repository_adapter.branch).and_return(encrypted_branch)
173
159
 
174
160
  encrypted_test_files = double
175
- expect(KnapsackPro::Crypto::Encryptor).to receive(:call).with(lazy_loaded_fast_and_slow_test_files_to_run).and_return(encrypted_test_files)
161
+ expect(KnapsackPro::Crypto::Encryptor).to receive(:call).with(fast_and_slow_test_files_to_run).and_return(encrypted_test_files)
176
162
 
177
163
  # 2nd request is no more an attempt to connect to queue.
178
164
  # We want to try to initalize a new queue so we will also send list of test files from disk.
@@ -212,32 +198,20 @@ describe KnapsackPro::QueueAllocator do
212
198
  let(:response2_errors?) { false }
213
199
 
214
200
  context 'when 2nd response returns test files (successful attempt to connect to queue already existing on the API side)' do
215
- let(:test_files) do
216
- [
217
- { 'path' => 'a_spec.rb' },
218
- { 'path' => 'b_spec.rb' },
219
- ]
220
- end
221
201
  let(:response2) do
222
- { 'test_files' => test_files }
202
+ {
203
+ 'test_files' => [
204
+ { 'path' => 'a_spec.rb' },
205
+ { 'path' => 'b_spec.rb' },
206
+ ]
207
+ }
223
208
  end
224
209
 
225
- context 'when test files encryption is enabled' do
226
- before do
227
- expect(KnapsackPro::Config::Env).to receive(:test_files_encrypted?).and_return(true)
228
- expect(KnapsackPro::Crypto::Decryptor).to receive(:call).with(lazy_loaded_fast_and_slow_test_files_to_run, response2['test_files']).and_return(test_files)
229
- end
230
-
231
- it { should eq ['a_spec.rb', 'b_spec.rb'] }
210
+ before do
211
+ expect(KnapsackPro::Crypto::Decryptor).to receive(:call).with(fast_and_slow_test_files_to_run, response2['test_files']).and_call_original
232
212
  end
233
213
 
234
- context 'when test files encryption is disabled' do
235
- before do
236
- expect(KnapsackPro::Config::Env).to receive(:test_files_encrypted?).and_return(false)
237
- end
238
-
239
- it { should eq ['a_spec.rb', 'b_spec.rb'] }
240
- end
214
+ it { should eq ['a_spec.rb', 'b_spec.rb'] }
241
215
  end
242
216
  end
243
217
  end
@@ -304,32 +278,20 @@ describe KnapsackPro::QueueAllocator do
304
278
  let(:errors?) { false }
305
279
 
306
280
  context 'when response returns test files (successful attempt to connect to queue already existing on the API side)' do
307
- let(:test_files) do
308
- [
309
- { 'path' => 'a_spec.rb' },
310
- { 'path' => 'b_spec.rb' },
311
- ]
312
- end
313
281
  let(:response) do
314
- { 'test_files' => test_files }
282
+ {
283
+ 'test_files' => [
284
+ { 'path' => 'a_spec.rb' },
285
+ { 'path' => 'b_spec.rb' },
286
+ ]
287
+ }
315
288
  end
316
289
 
317
- context 'when test files encryption is enabled' do
318
- before do
319
- expect(KnapsackPro::Config::Env).to receive(:test_files_encrypted?).and_return(true)
320
- expect(KnapsackPro::Crypto::Decryptor).to receive(:call).with(lazy_loaded_fast_and_slow_test_files_to_run, response['test_files']).and_return(test_files)
321
- end
322
-
323
- it { should eq ['a_spec.rb', 'b_spec.rb'] }
290
+ before do
291
+ expect(KnapsackPro::Crypto::Decryptor).to receive(:call).with(fast_and_slow_test_files_to_run, response['test_files']).and_call_original
324
292
  end
325
293
 
326
- context 'when test files encryption is disabled' do
327
- before do
328
- expect(KnapsackPro::Config::Env).to receive(:test_files_encrypted?).and_return(false)
329
- end
330
-
331
- it { should eq ['a_spec.rb', 'b_spec.rb'] }
332
- end
294
+ it { should eq ['a_spec.rb', 'b_spec.rb'] }
333
295
  end
334
296
  end
335
297
  end
@@ -34,6 +34,8 @@ describe KnapsackPro::Runners::CucumberRunner do
34
34
  let(:task) { double }
35
35
 
36
36
  before do
37
+ expect(KnapsackPro::Adapters::CucumberAdapter).to receive(:verify_bind_method_called)
38
+
37
39
  expect(Rake::Task).to receive(:[]).with('knapsack_pro:cucumber_run').at_least(1).and_return(task)
38
40
 
39
41
  t = double
@@ -14,6 +14,10 @@ describe KnapsackPro::Runners::MinitestRunner do
14
14
  end
15
15
 
16
16
  context 'when test files were returned by Knapsack Pro API' do
17
+ before do
18
+ expect(KnapsackPro::Adapters::MinitestAdapter).to receive(:verify_bind_method_called)
19
+ end
20
+
17
21
  it 'runs tests' do
18
22
  test_file_paths = ['test_fake/a_test.rb', 'test_fake/b_test.rb']
19
23
  runner = instance_double(described_class,
@@ -167,14 +167,34 @@ describe KnapsackPro::Runners::Queue::CucumberRunner do
167
167
  context "when test files don't exist" do
168
168
  let(:test_file_paths) { [] }
169
169
 
170
- it 'returns exit code 0' do
171
- expect(KnapsackPro::Hooks::Queue).to receive(:call_after_queue)
172
- expect(KnapsackPro::Report).to receive(:save_node_queue_to_api)
170
+ context 'when all_test_file_paths exist' do
171
+ let(:all_test_file_paths) { ['features/a.feature'] }
173
172
 
174
- expect(subject).to eq({
175
- status: :completed,
176
- exitstatus: exitstatus,
177
- })
173
+ it 'returns exit code 0' do
174
+ expect(KnapsackPro::Adapters::CucumberAdapter).to receive(:verify_bind_method_called)
175
+
176
+ expect(KnapsackPro::Hooks::Queue).to receive(:call_after_queue)
177
+ expect(KnapsackPro::Report).to receive(:save_node_queue_to_api)
178
+
179
+ expect(subject).to eq({
180
+ status: :completed,
181
+ exitstatus: exitstatus,
182
+ })
183
+ end
184
+ end
185
+
186
+ context "when all_test_file_paths don't exist" do
187
+ let(:all_test_file_paths) { [] }
188
+
189
+ it 'returns exit code 0' do
190
+ expect(KnapsackPro::Hooks::Queue).to receive(:call_after_queue)
191
+ expect(KnapsackPro::Report).to receive(:save_node_queue_to_api)
192
+
193
+ expect(subject).to eq({
194
+ status: :completed,
195
+ exitstatus: exitstatus,
196
+ })
197
+ end
178
198
  end
179
199
  end
180
200
  end
@@ -159,14 +159,34 @@ describe KnapsackPro::Runners::Queue::MinitestRunner do
159
159
  context "when test files don't exist" do
160
160
  let(:test_file_paths) { [] }
161
161
 
162
- it 'returns exit code 0' do
163
- expect(KnapsackPro::Hooks::Queue).to receive(:call_after_queue)
164
- expect(KnapsackPro::Report).to receive(:save_node_queue_to_api)
162
+ context 'when all_test_file_paths exist' do
163
+ let(:all_test_file_paths) { ['a_test.rb'] }
165
164
 
166
- expect(subject).to eq({
167
- status: :completed,
168
- exitstatus: exitstatus,
169
- })
165
+ it 'returns exit code 0' do
166
+ expect(KnapsackPro::Adapters::MinitestAdapter).to receive(:verify_bind_method_called)
167
+
168
+ expect(KnapsackPro::Hooks::Queue).to receive(:call_after_queue)
169
+ expect(KnapsackPro::Report).to receive(:save_node_queue_to_api)
170
+
171
+ expect(subject).to eq({
172
+ status: :completed,
173
+ exitstatus: exitstatus,
174
+ })
175
+ end
176
+ end
177
+
178
+ context "when all_test_file_paths don't exist" do
179
+ let(:all_test_file_paths) { [] }
180
+
181
+ it 'returns exit code 0' do
182
+ expect(KnapsackPro::Hooks::Queue).to receive(:call_after_queue)
183
+ expect(KnapsackPro::Report).to receive(:save_node_queue_to_api)
184
+
185
+ expect(subject).to eq({
186
+ status: :completed,
187
+ exitstatus: exitstatus,
188
+ })
189
+ end
170
190
  end
171
191
  end
172
192
  end
@@ -249,6 +249,8 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do
249
249
  let(:all_test_file_paths) { ['a_spec.rb'] }
250
250
 
251
251
  it do
252
+ expect(KnapsackPro::Adapters::RSpecAdapter).to receive(:verify_bind_method_called)
253
+
252
254
  expect(KnapsackPro::Formatters::RSpecQueueSummaryFormatter).to receive(:print_summary)
253
255
  expect(KnapsackPro::Formatters::RSpecQueueProfileFormatterExtension).to receive(:print_summary)
254
256
 
@@ -34,6 +34,8 @@ describe KnapsackPro::Runners::RSpecRunner do
34
34
  let(:task) { double }
35
35
 
36
36
  before do
37
+ expect(KnapsackPro::Adapters::RSpecAdapter).to receive(:verify_bind_method_called)
38
+
37
39
  expect(Rake::Task).to receive(:[]).with('knapsack_pro:rspec_run').at_least(1).and_return(task)
38
40
 
39
41
  t = double
@@ -26,6 +26,8 @@ describe KnapsackPro::Runners::SpinachRunner do
26
26
  end
27
27
 
28
28
  before do
29
+ expect(KnapsackPro::Adapters::SpinachAdapter).to receive(:verify_bind_method_called)
30
+
29
31
  expect(Kernel).to receive(:system).with('KNAPSACK_PRO_RECORDING_ENABLED=true KNAPSACK_PRO_TEST_SUITE_TOKEN=spinach-token bundle exec spinach --custom-arg --features_path fake-test-dir -- features/a.feature features/b.feature')
30
32
  end
31
33
 
@@ -16,6 +16,8 @@ describe KnapsackPro::Runners::TestUnitRunner do
16
16
 
17
17
  context 'when test files were returned by Knapsack Pro API' do
18
18
  it 'runs tests' do
19
+ expect(KnapsackPro::Adapters::TestUnitAdapter).to receive(:verify_bind_method_called)
20
+
19
21
  test_file_paths = ['test-unit_fake/a_test.rb', 'test-unit_fake/b_test.rb']
20
22
  runner = instance_double(described_class,
21
23
  test_dir: 'test-unit_fake',
@@ -12,9 +12,7 @@ describe KnapsackPro::Tracker do
12
12
  subject { tracker.current_test_path }
13
13
 
14
14
  context 'when current_test_path not set' do
15
- it do
16
- expect { subject }.to raise_error("current_test_path needs to be set by Knapsack Pro Adapter's bind method")
17
- end
15
+ it { expect(subject).to be_nil }
18
16
  end
19
17
 
20
18
  context 'when current_test_path set' do
@@ -58,6 +56,9 @@ describe KnapsackPro::Tracker do
58
56
  it { expect(tracker.test_files_with_time.keys.size).to eql 2 }
59
57
  it { expect(tracker.test_files_with_time['a_spec.rb'][:time_execution]).to be_within(delta).of(0.1) }
60
58
  it { expect(tracker.test_files_with_time['b_spec.rb'][:time_execution]).to be_within(delta).of(0.2) }
59
+ it 'resets current_test_path after time is measured' do
60
+ expect(tracker.current_test_path).to be_nil
61
+ end
61
62
  it_behaves_like '#to_a'
62
63
  end
63
64
 
@@ -83,6 +84,9 @@ describe KnapsackPro::Tracker do
83
84
  it { expect(tracker.test_files_with_time.keys.size).to eql 2 }
84
85
  it { expect(tracker.test_files_with_time['a_spec.rb'][:time_execution]).to be_within(delta).of(0) }
85
86
  it { expect(tracker.test_files_with_time['b_spec.rb'][:time_execution]).to be_within(delta).of(0) }
87
+ it 'resets current_test_path after time is measured' do
88
+ expect(tracker.current_test_path).to be_nil
89
+ end
86
90
  it_behaves_like '#to_a'
87
91
  end
88
92
 
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: 2.10.0
4
+ version: 2.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ArturT
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-25 00:00:00.000000000 Z
11
+ date: 2021-04-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -408,7 +408,7 @@ metadata:
408
408
  documentation_uri: https://docs.knapsackpro.com/integration/
409
409
  homepage_uri: https://knapsackpro.com
410
410
  source_code_uri: https://github.com/KnapsackPro/knapsack_pro-ruby
411
- post_install_message:
411
+ post_install_message:
412
412
  rdoc_options: []
413
413
  require_paths:
414
414
  - lib
@@ -424,7 +424,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
424
424
  version: '0'
425
425
  requirements: []
426
426
  rubygems_version: 3.0.6
427
- signing_key:
427
+ signing_key:
428
428
  specification_version: 4
429
429
  summary: Knapsack Pro splits tests across parallel CI nodes and ensures each parallel
430
430
  job finish work at a similar time.