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