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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +40 -0
- data/README.md +31 -1562
- data/lib/knapsack_pro/adapters/base_adapter.rb +22 -0
- data/lib/knapsack_pro/adapters/rspec_adapter.rb +6 -2
- data/lib/knapsack_pro/allocator.rb +1 -1
- data/lib/knapsack_pro/base_allocator_builder.rb +0 -8
- data/lib/knapsack_pro/config/env.rb +1 -0
- data/lib/knapsack_pro/queue_allocator.rb +9 -20
- data/lib/knapsack_pro/queue_allocator_builder.rb +2 -2
- data/lib/knapsack_pro/report.rb +1 -1
- data/lib/knapsack_pro/runners/cucumber_runner.rb +4 -1
- data/lib/knapsack_pro/runners/minitest_runner.rb +4 -1
- data/lib/knapsack_pro/runners/queue/cucumber_runner.rb +4 -0
- data/lib/knapsack_pro/runners/queue/minitest_runner.rb +4 -0
- data/lib/knapsack_pro/runners/queue/rspec_runner.rb +2 -0
- data/lib/knapsack_pro/runners/rspec_runner.rb +4 -1
- data/lib/knapsack_pro/runners/spinach_runner.rb +4 -1
- data/lib/knapsack_pro/runners/test_unit_runner.rb +4 -1
- data/lib/knapsack_pro/slow_test_file_determiner.rb +1 -1
- data/lib/knapsack_pro/test_case_detectors/rspec_test_example_detector.rb +1 -1
- data/lib/knapsack_pro/tracker.rb +10 -6
- data/lib/knapsack_pro/version.rb +1 -1
- data/spec/knapsack_pro/adapters/base_adapter_spec.rb +51 -0
- data/spec/knapsack_pro/adapters/rspec_adapter_spec.rb +15 -9
- data/spec/knapsack_pro/queue_allocator_builder_spec.rb +6 -6
- data/spec/knapsack_pro/queue_allocator_spec.rb +33 -71
- data/spec/knapsack_pro/runners/cucumber_runner_spec.rb +2 -0
- data/spec/knapsack_pro/runners/minitest_runner_spec.rb +4 -0
- data/spec/knapsack_pro/runners/queue/cucumber_runner_spec.rb +27 -7
- data/spec/knapsack_pro/runners/queue/minitest_runner_spec.rb +27 -7
- data/spec/knapsack_pro/runners/queue/rspec_runner_spec.rb +2 -0
- data/spec/knapsack_pro/runners/rspec_runner_spec.rb +2 -0
- data/spec/knapsack_pro/runners/spinach_runner_spec.rb +2 -0
- data/spec/knapsack_pro/runners/test_unit_runner_spec.rb +2 -0
- data/spec/knapsack_pro/tracker_spec.rb +7 -3
- metadata +5 -5
@@ -8,11 +8,11 @@ describe KnapsackPro::QueueAllocatorBuilder do
|
|
8
8
|
subject { allocator_builder.allocator }
|
9
9
|
|
10
10
|
before do
|
11
|
-
|
12
|
-
expect(allocator_builder).to receive(:
|
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
|
-
|
15
|
-
expect(allocator_builder).to receive(:
|
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
|
-
|
29
|
-
|
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(:
|
3
|
-
let(:
|
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
|
-
|
14
|
-
|
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(
|
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
|
-
{
|
135
|
+
{
|
136
|
+
'test_files' => [
|
137
|
+
{ 'path' => 'a_spec.rb' },
|
138
|
+
{ 'path' => 'b_spec.rb' },
|
139
|
+
]
|
140
|
+
}
|
144
141
|
end
|
145
142
|
|
146
|
-
|
147
|
-
|
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
|
-
|
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(
|
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
|
-
{
|
202
|
+
{
|
203
|
+
'test_files' => [
|
204
|
+
{ 'path' => 'a_spec.rb' },
|
205
|
+
{ 'path' => 'b_spec.rb' },
|
206
|
+
]
|
207
|
+
}
|
223
208
|
end
|
224
209
|
|
225
|
-
|
226
|
-
|
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
|
-
|
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
|
-
{
|
282
|
+
{
|
283
|
+
'test_files' => [
|
284
|
+
{ 'path' => 'a_spec.rb' },
|
285
|
+
{ 'path' => 'b_spec.rb' },
|
286
|
+
]
|
287
|
+
}
|
315
288
|
end
|
316
289
|
|
317
|
-
|
318
|
-
|
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
|
-
|
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
|
-
|
171
|
-
|
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
|
-
|
175
|
-
|
176
|
-
|
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
|
-
|
163
|
-
|
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
|
-
|
167
|
-
|
168
|
-
|
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
|
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.
|
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:
|
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.
|