knapsack_pro 7.2.0 → 7.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +14 -0
- data/CHANGELOG.md +71 -0
- data/lib/knapsack_pro/batch.rb +20 -0
- data/lib/knapsack_pro/config/env.rb +24 -26
- data/lib/knapsack_pro/extensions/rspec_extension.rb +7 -2
- data/lib/knapsack_pro/hooks/queue.rb +7 -4
- data/lib/knapsack_pro/queue.rb +40 -0
- data/lib/knapsack_pro/runners/queue/rspec_runner.rb +6 -3
- data/lib/knapsack_pro/version.rb +1 -1
- data/lib/knapsack_pro.rb +2 -0
- data/spec/integration/runners/queue/rspec_runner_spec.rb +133 -0
- data/spec/knapsack_pro/config/env_spec.rb +294 -9
- data/spec/knapsack_pro/hooks/queue_spec.rb +90 -48
- data/spec/knapsack_pro/queue_spec.rb +35 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 965d1d9b1d138cf0db8abe0fb44fc1672d5992d9f40f014c0f1f72c370d82585
|
4
|
+
data.tar.gz: 9570a9c2ffd20d1324451106f7a6144a298b6efb02981eabdc1f354d5c289940
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e7b335edb2e4107b44b0bf69b7cffdf0af110e316ad3d1f07190d919e23fe7172cae3081c5f97450174f1e0597f9d71387dafd8a0861aca604531a9cb1b1c26c
|
7
|
+
data.tar.gz: 269bc36e25e5a2048f2105f973523bc00dfba73b38ebf7eac482b121a8cd22a129f72c671579bd230830bcb3aa600428d2f7a5a3410ce1515c7ee4353fc36dde
|
data/.circleci/config.yml
CHANGED
@@ -152,6 +152,12 @@ jobs:
|
|
152
152
|
command: |
|
153
153
|
export KNAPSACK_PRO_BRANCH="$CIRCLE_BRANCH--$CIRCLE_BUILD_NUM--regular"
|
154
154
|
bundle exec rake knapsack_pro:rspec
|
155
|
+
- run:
|
156
|
+
working_directory: ~/rails-app-with-knapsack_pro
|
157
|
+
command: |
|
158
|
+
# retry the same split ||
|
159
|
+
export KNAPSACK_PRO_BRANCH="$CIRCLE_BRANCH--$CIRCLE_BUILD_NUM--regular"
|
160
|
+
bundle exec rake knapsack_pro:rspec
|
155
161
|
- run:
|
156
162
|
working_directory: ~/rails-app-with-knapsack_pro
|
157
163
|
command: |
|
@@ -285,6 +291,7 @@ jobs:
|
|
285
291
|
RACK_ENV: test
|
286
292
|
KNAPSACK_PRO_ENDPOINT: https://api-staging.knapsackpro.com
|
287
293
|
KNAPSACK_PRO_TEST_SUITE_TOKEN_MINITEST: $KNAPSACK_PRO_TEST_SUITE_TOKEN_MINITEST
|
294
|
+
KNAPSACK_PRO_RSPEC_DISABLED: true
|
288
295
|
EXTRA_TEST_FILES_DELAY: 10
|
289
296
|
- image: cimg/postgres:14.7
|
290
297
|
environment:
|
@@ -308,6 +315,12 @@ jobs:
|
|
308
315
|
command: |
|
309
316
|
export KNAPSACK_PRO_BRANCH="$CIRCLE_BRANCH--$CIRCLE_BUILD_NUM--regular"
|
310
317
|
bundle exec rake knapsack_pro:minitest[--verbose]
|
318
|
+
- run:
|
319
|
+
working_directory: ~/rails-app-with-knapsack_pro
|
320
|
+
command: |
|
321
|
+
# retry the same split ||
|
322
|
+
export KNAPSACK_PRO_BRANCH="$CIRCLE_BRANCH--$CIRCLE_BUILD_NUM--regular"
|
323
|
+
bundle exec rake knapsack_pro:minitest[--verbose]
|
311
324
|
|
312
325
|
e2e-queue-minitest:
|
313
326
|
parameters:
|
@@ -325,6 +338,7 @@ jobs:
|
|
325
338
|
RACK_ENV: test
|
326
339
|
KNAPSACK_PRO_ENDPOINT: https://api-staging.knapsackpro.com
|
327
340
|
KNAPSACK_PRO_TEST_SUITE_TOKEN_MINITEST: $KNAPSACK_PRO_TEST_SUITE_TOKEN_MINITEST
|
341
|
+
KNAPSACK_PRO_RSPEC_DISABLED: true
|
328
342
|
EXTRA_TEST_FILES_DELAY: 10
|
329
343
|
- image: cimg/postgres:14.7
|
330
344
|
environment:
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,57 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
### 7.4.0
|
4
|
+
* Warn when `KNAPSACK_PRO_*` environment variables are set manually if their values could be automatically determined from supported CI environments.
|
5
|
+
|
6
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/254
|
7
|
+
|
8
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v7.3.0...v7.4.0
|
9
|
+
|
10
|
+
### 7.3.0
|
11
|
+
|
12
|
+
* [Queue Mode][RSpec] Pass each batch of tests to the queue hooks: `KnapsackPro::Hooks::Queue.before_subset_queue` and `KnapsackPro::Hooks::Queue.after_subset_queue`
|
13
|
+
|
14
|
+
The `KnapsackPro::Hooks::Queue.before_subset_queue` and `KnapsackPro::Hooks::Queue.after_subset_queue` hooks get a 3rd variable - the `queue`.
|
15
|
+
|
16
|
+
The `queue` variable stores an enumerable collection with each batch of tests fetched from the Queue API. The batch has:
|
17
|
+
|
18
|
+
* a list of test file paths (`KnapsackPro::Batch#test_file_paths` returns an array like `['a_spec.rb', 'b_spec.rb']`)
|
19
|
+
* a status of the given set of tests in the batch (`KnapsackPro::Batch#status` returns `:not_executed`, `:passed` or `:failed`)
|
20
|
+
|
21
|
+
Example usage:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
# spec_helper.rb
|
25
|
+
|
26
|
+
KnapsackPro::Hooks::Queue.before_subset_queue do |queue_id, subset_queue_id, queue|
|
27
|
+
print "Tests from all batches fetched from the Queue API so far: "
|
28
|
+
puts queue.map(&:test_file_paths).inspect
|
29
|
+
|
30
|
+
queue.each(&:test_file_paths) # you can use each as well
|
31
|
+
|
32
|
+
print "Current batch tests: "
|
33
|
+
puts queue.current_batch.test_file_paths.inspect
|
34
|
+
|
35
|
+
print "Current batch status: "
|
36
|
+
puts queue.current_batch.status # returns :not_executed in the `before_subset_queue` hook
|
37
|
+
end
|
38
|
+
|
39
|
+
KnapsackPro::Hooks::Queue.after_subset_queue do |queue_id, subset_queue_id, queue|
|
40
|
+
print "Tests from all batches fetched from the Queue API so far: "
|
41
|
+
puts queue.map(&:test_file_paths).inspect
|
42
|
+
|
43
|
+
print "Current batch tests: "
|
44
|
+
puts queue.current_batch.test_file_paths.inspect
|
45
|
+
|
46
|
+
print "Current batch status: "
|
47
|
+
puts queue.current_batch.status # returns :passed or :failed in the `after_subset_queue` hook
|
48
|
+
end
|
49
|
+
```
|
50
|
+
|
51
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/253
|
52
|
+
|
53
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v7.2.0...v7.3.0
|
54
|
+
|
3
55
|
### 7.2.0
|
4
56
|
|
5
57
|
* Always use the original `Net::HTTP` client, even when WebMock replaces it with its own
|
@@ -47,6 +99,25 @@ https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v7.0.0...v7.0.1
|
|
47
99
|
__After:__<br>
|
48
100
|
The `before(:suite)` and `after(:suite)` hooks are executed only once: `before(:suite)` is executed before starting tests, `after(:suite)` is executed after all tests are completed. (It is what you would expect from RSpec).
|
49
101
|
|
102
|
+
* It is recommended that you define your `before(:suite)` hooks in `spec_helper.rb` or `rails_helper.rb`. These files should be loaded before any test files so that the hook is registered by RSpec.
|
103
|
+
|
104
|
+
The `before(:suite)` hook is executed first. After that, test files are dynamically loaded in multiple batches from the Knapsack Pro Queue API. __The `before(:suite)` hooks defined in test files won't be executed because it is too late!__
|
105
|
+
|
106
|
+
If you need to have something that is similar to `before(:suite)` and you want to define it in a test file, then you can use this:
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
RSpec.configure do |config|
|
110
|
+
config.before(:context) do
|
111
|
+
unless ENV['MY_HOOK_NAME']
|
112
|
+
# your code to run in the hook
|
113
|
+
end
|
114
|
+
ENV['MY_HOOK_NAME'] = 'hook_called'
|
115
|
+
end
|
116
|
+
end
|
117
|
+
```
|
118
|
+
|
119
|
+
Alternatively, if you need to [load code only once for a specific type of specs you can check this](https://docs.knapsackpro.com/ruby/rspec/#load-code-only-once-for-a-specific-type-of-specs).
|
120
|
+
|
50
121
|
* The `KnapsackPro::Hooks::Queue.after_queue` hook change:
|
51
122
|
|
52
123
|
__Before:__<br>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KnapsackPro
|
4
|
+
class Batch
|
5
|
+
attr_reader :test_file_paths, :status
|
6
|
+
|
7
|
+
def initialize(test_file_paths)
|
8
|
+
@test_file_paths = test_file_paths
|
9
|
+
@status = :not_executed
|
10
|
+
end
|
11
|
+
|
12
|
+
def _passed
|
13
|
+
@status = :passed
|
14
|
+
end
|
15
|
+
|
16
|
+
def _failed
|
17
|
+
@status = :failed
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -13,30 +13,21 @@ module KnapsackPro
|
|
13
13
|
|
14
14
|
class << self
|
15
15
|
def ci_node_total
|
16
|
-
(
|
17
|
-
ci_env_for(:node_total) ||
|
18
|
-
1).to_i
|
16
|
+
(env_for('KNAPSACK_PRO_CI_NODE_TOTAL', :node_total) || 1).to_i
|
19
17
|
end
|
20
18
|
|
21
19
|
def ci_node_index
|
22
|
-
(
|
23
|
-
ci_env_for(:node_index) ||
|
24
|
-
0).to_i
|
20
|
+
(env_for('KNAPSACK_PRO_CI_NODE_INDEX', :node_index) || 0).to_i
|
25
21
|
end
|
26
22
|
|
27
23
|
def ci_node_build_id
|
28
24
|
env_name = 'KNAPSACK_PRO_CI_NODE_BUILD_ID'
|
29
|
-
|
30
|
-
ci_env_for(:node_build_id) ||
|
25
|
+
env_for(env_name, :node_build_id) ||
|
31
26
|
raise("Missing environment variable #{env_name}. Read more at #{KnapsackPro::Urls::KNAPSACK_PRO_CI_NODE_BUILD_ID}")
|
32
27
|
end
|
33
28
|
|
34
29
|
def ci_node_retry_count
|
35
|
-
(
|
36
|
-
ENV['KNAPSACK_PRO_CI_NODE_RETRY_COUNT'] ||
|
37
|
-
ci_env_for(:node_retry_count) ||
|
38
|
-
0
|
39
|
-
).to_i
|
30
|
+
(env_for('KNAPSACK_PRO_CI_NODE_RETRY_COUNT', :node_retry_count) || 0).to_i
|
40
31
|
end
|
41
32
|
|
42
33
|
def max_request_retries
|
@@ -47,23 +38,19 @@ module KnapsackPro
|
|
47
38
|
end
|
48
39
|
|
49
40
|
def commit_hash
|
50
|
-
|
51
|
-
ci_env_for(:commit_hash)
|
41
|
+
env_for('KNAPSACK_PRO_COMMIT_HASH', :commit_hash)
|
52
42
|
end
|
53
43
|
|
54
44
|
def branch
|
55
|
-
|
56
|
-
ci_env_for(:branch)
|
45
|
+
env_for('KNAPSACK_PRO_BRANCH', :branch)
|
57
46
|
end
|
58
47
|
|
59
48
|
def project_dir
|
60
|
-
|
61
|
-
ci_env_for(:project_dir)
|
49
|
+
env_for('KNAPSACK_PRO_PROJECT_DIR', :project_dir)
|
62
50
|
end
|
63
51
|
|
64
52
|
def user_seat
|
65
|
-
|
66
|
-
ci_env_for(:user_seat)
|
53
|
+
env_for('KNAPSACK_PRO_USER_SEAT', :user_seat)
|
67
54
|
end
|
68
55
|
|
69
56
|
def masked_user_seat
|
@@ -183,7 +170,7 @@ module KnapsackPro
|
|
183
170
|
def fixed_queue_split
|
184
171
|
@fixed_queue_split ||= begin
|
185
172
|
env_name = 'KNAPSACK_PRO_FIXED_QUEUE_SPLIT'
|
186
|
-
computed =
|
173
|
+
computed = env_for(env_name, :fixed_queue_split).to_s
|
187
174
|
|
188
175
|
if !ENV.key?(env_name)
|
189
176
|
KnapsackPro.logger.info("#{env_name} is not set. Using default value: #{computed}. Learn more at #{KnapsackPro::Urls::FIXED_QUEUE_SPLIT}")
|
@@ -249,10 +236,6 @@ module KnapsackPro
|
|
249
236
|
end
|
250
237
|
end
|
251
238
|
|
252
|
-
def ci_env_for(env_name)
|
253
|
-
detected_ci.new.send(env_name)
|
254
|
-
end
|
255
|
-
|
256
239
|
def detected_ci
|
257
240
|
detected = KnapsackPro::Config::CI.constants.map do |constant|
|
258
241
|
Object.const_get("KnapsackPro::Config::CI::#{constant}").new.detected
|
@@ -293,6 +276,21 @@ module KnapsackPro
|
|
293
276
|
def required_env(env_name)
|
294
277
|
ENV[env_name] || raise("Missing environment variable #{env_name}")
|
295
278
|
end
|
279
|
+
|
280
|
+
def env_for(knapsack_env_name, ci_env_method)
|
281
|
+
knapsack_env_value = ENV[knapsack_env_name]
|
282
|
+
ci_env_value = ci_env_for(ci_env_method)
|
283
|
+
|
284
|
+
if !knapsack_env_value.nil? && !ci_env_value.nil? && knapsack_env_value != ci_env_value.to_s
|
285
|
+
KnapsackPro.logger.info("You have set the environment variable #{knapsack_env_name} to #{knapsack_env_value} which could be automatically determined from the CI environment as #{ci_env_value}.")
|
286
|
+
end
|
287
|
+
|
288
|
+
knapsack_env_value != nil ? knapsack_env_value : ci_env_value
|
289
|
+
end
|
290
|
+
|
291
|
+
def ci_env_for(env_name)
|
292
|
+
detected_ci.new.send(env_name)
|
293
|
+
end
|
296
294
|
end
|
297
295
|
end
|
298
296
|
end
|
@@ -90,7 +90,7 @@ module KnapsackPro
|
|
90
90
|
|
91
91
|
configuration.reporter.report(_expected_example_count = 0) do |reporter|
|
92
92
|
configuration.with_suite_hooks do
|
93
|
-
queue_runner.with_batch do |test_file_paths|
|
93
|
+
queue_runner.with_batch do |test_file_paths, queue|
|
94
94
|
knapsack__load_spec_files_batch(test_file_paths)
|
95
95
|
|
96
96
|
examples_passed = ordering_strategy.order(world.example_groups).map do |example_group|
|
@@ -98,7 +98,12 @@ module KnapsackPro
|
|
98
98
|
example_group.run(reporter)
|
99
99
|
end.all?
|
100
100
|
|
101
|
-
|
101
|
+
if examples_passed
|
102
|
+
queue.mark_batch_passed
|
103
|
+
else
|
104
|
+
queue.mark_batch_failed
|
105
|
+
node_examples_passed = false
|
106
|
+
end
|
102
107
|
|
103
108
|
knapsack__persist_example_statuses
|
104
109
|
|
@@ -54,22 +54,25 @@ module KnapsackPro
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
-
|
57
|
+
# `queue` is always present for RSpec
|
58
|
+
def call_before_subset_queue(queue = nil)
|
58
59
|
return unless before_subset_queue_store
|
59
60
|
before_subset_queue_store.each do |block|
|
60
61
|
block.call(
|
61
62
|
KnapsackPro::Config::Env.queue_id,
|
62
|
-
KnapsackPro::Config::Env.subset_queue_id
|
63
|
+
KnapsackPro::Config::Env.subset_queue_id,
|
64
|
+
queue
|
63
65
|
)
|
64
66
|
end
|
65
67
|
end
|
66
68
|
|
67
|
-
def call_after_subset_queue
|
69
|
+
def call_after_subset_queue(queue = nil)
|
68
70
|
return unless after_subset_queue_store
|
69
71
|
after_subset_queue_store.each do |block|
|
70
72
|
block.call(
|
71
73
|
KnapsackPro::Config::Env.queue_id,
|
72
|
-
KnapsackPro::Config::Env.subset_queue_id
|
74
|
+
KnapsackPro::Config::Env.subset_queue_id,
|
75
|
+
queue
|
73
76
|
)
|
74
77
|
end
|
75
78
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KnapsackPro
|
4
|
+
class Queue
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@batches = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def each(&block)
|
12
|
+
@batches.each(&block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_batch_for(test_file_paths)
|
16
|
+
return if test_file_paths.empty?
|
17
|
+
@batches << KnapsackPro::Batch.new(test_file_paths)
|
18
|
+
end
|
19
|
+
|
20
|
+
def mark_batch_passed
|
21
|
+
current_batch._passed
|
22
|
+
end
|
23
|
+
|
24
|
+
def mark_batch_failed
|
25
|
+
current_batch._failed
|
26
|
+
end
|
27
|
+
|
28
|
+
def current_batch
|
29
|
+
@batches.last
|
30
|
+
end
|
31
|
+
|
32
|
+
def size
|
33
|
+
@batches.size
|
34
|
+
end
|
35
|
+
|
36
|
+
def [](index)
|
37
|
+
@batches[index]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -33,6 +33,7 @@ module KnapsackPro
|
|
33
33
|
@stream_out = stream_out
|
34
34
|
@node_test_file_paths = []
|
35
35
|
@rspec_runner = nil # RSpec::Core::Runner is lazy initialized
|
36
|
+
@queue = KnapsackPro::Queue.new
|
36
37
|
end
|
37
38
|
|
38
39
|
# Based on:
|
@@ -82,11 +83,13 @@ module KnapsackPro
|
|
82
83
|
subset_queue_id = KnapsackPro::Config::EnvGenerator.set_subset_queue_id
|
83
84
|
ENV['KNAPSACK_PRO_SUBSET_QUEUE_ID'] = subset_queue_id
|
84
85
|
|
85
|
-
|
86
|
+
@queue.add_batch_for(test_file_paths)
|
86
87
|
|
87
|
-
|
88
|
+
KnapsackPro::Hooks::Queue.call_before_subset_queue(@queue)
|
88
89
|
|
89
|
-
|
90
|
+
yield test_file_paths, @queue
|
91
|
+
|
92
|
+
KnapsackPro::Hooks::Queue.call_after_subset_queue(@queue)
|
90
93
|
|
91
94
|
if @rspec_runner.knapsack__wants_to_quit?
|
92
95
|
KnapsackPro.logger.warn('RSpec wants to quit.')
|
data/lib/knapsack_pro/version.rb
CHANGED
data/lib/knapsack_pro.rb
CHANGED
@@ -67,6 +67,8 @@ require_relative 'knapsack_pro/test_files_with_test_cases_composer'
|
|
67
67
|
require_relative 'knapsack_pro/base_allocator_builder'
|
68
68
|
require_relative 'knapsack_pro/allocator_builder'
|
69
69
|
require_relative 'knapsack_pro/queue_allocator_builder'
|
70
|
+
require_relative 'knapsack_pro/batch'
|
71
|
+
require_relative 'knapsack_pro/queue'
|
70
72
|
require_relative 'knapsack_pro/runners/base_runner'
|
71
73
|
require_relative 'knapsack_pro/runners/rspec_runner'
|
72
74
|
require_relative 'knapsack_pro/runners/cucumber_runner'
|
@@ -739,6 +739,139 @@ describe "#{KnapsackPro::Runners::Queue::RSpecRunner} - Integration tests", :cle
|
|
739
739
|
|
740
740
|
expect(actual.exit_code).to eq 0
|
741
741
|
end
|
742
|
+
|
743
|
+
it 'gives access to batch of tests in queue hooks' do
|
744
|
+
rspec_options = ''
|
745
|
+
|
746
|
+
spec_helper = <<~SPEC
|
747
|
+
require 'knapsack_pro'
|
748
|
+
KnapsackPro::Adapters::RSpecAdapter.bind
|
749
|
+
|
750
|
+
KnapsackPro::Hooks::Queue.before_subset_queue do |queue_id, subset_queue_id, queue|
|
751
|
+
print "Tests in batches in before_subset_queue: "
|
752
|
+
puts queue.map(&:test_file_paths).inspect
|
753
|
+
|
754
|
+
print "Batches' statuses in before_subset_queue: "
|
755
|
+
puts queue.map(&:status).inspect
|
756
|
+
end
|
757
|
+
|
758
|
+
KnapsackPro::Hooks::Queue.after_subset_queue do |queue_id, subset_queue_id, queue|
|
759
|
+
print "Tests in batches in after_subset_queue: "
|
760
|
+
puts queue.map(&:test_file_paths).inspect
|
761
|
+
print "Batches' statuses in after_subset_queue: "
|
762
|
+
puts queue.map(&:status).inspect
|
763
|
+
|
764
|
+
# call public API methods that must be backward compatible
|
765
|
+
print "Current batch tests: "
|
766
|
+
puts queue.current_batch.test_file_paths.inspect
|
767
|
+
print "Current batch status: "
|
768
|
+
puts queue.current_batch.status
|
769
|
+
end
|
770
|
+
SPEC
|
771
|
+
|
772
|
+
spec_a = Spec.new('a_spec.rb', <<~SPEC)
|
773
|
+
describe 'A_describe' do
|
774
|
+
it 'A1 test example' do
|
775
|
+
expect(1).to eq 1
|
776
|
+
end
|
777
|
+
end
|
778
|
+
SPEC
|
779
|
+
|
780
|
+
spec_b = Spec.new('b_spec.rb', <<~SPEC)
|
781
|
+
describe 'B_describe' do
|
782
|
+
it 'B1 test example' do
|
783
|
+
expect(1).to eq 1
|
784
|
+
end
|
785
|
+
end
|
786
|
+
SPEC
|
787
|
+
|
788
|
+
spec_c = Spec.new('c_spec.rb', <<~SPEC)
|
789
|
+
describe 'C_describe' do
|
790
|
+
it 'C1 test example' do
|
791
|
+
expect(1).to eq 1
|
792
|
+
end
|
793
|
+
end
|
794
|
+
SPEC
|
795
|
+
|
796
|
+
failing_spec_d = Spec.new('d_spec.rb', <<~SPEC)
|
797
|
+
describe 'D_describe' do
|
798
|
+
it 'D1 test example' do
|
799
|
+
expect(1).to eq 0
|
800
|
+
end
|
801
|
+
end
|
802
|
+
SPEC
|
803
|
+
|
804
|
+
spec_e = Spec.new('e_spec.rb', <<~SPEC)
|
805
|
+
describe 'E_describe' do
|
806
|
+
it 'E1 test example' do
|
807
|
+
expect(1).to eq 1
|
808
|
+
end
|
809
|
+
end
|
810
|
+
SPEC
|
811
|
+
|
812
|
+
spec_f = Spec.new('f_spec.rb', <<~SPEC)
|
813
|
+
describe 'F_describe' do
|
814
|
+
it 'F1 test example' do
|
815
|
+
expect(1).to eq 1
|
816
|
+
end
|
817
|
+
end
|
818
|
+
SPEC
|
819
|
+
|
820
|
+
failing_spec_g = Spec.new('g_spec.rb', <<~SPEC)
|
821
|
+
describe 'G_describe' do
|
822
|
+
it 'G1 test example' do
|
823
|
+
expect(1).to eq 0
|
824
|
+
end
|
825
|
+
end
|
826
|
+
SPEC
|
827
|
+
|
828
|
+
spec_h = Spec.new('h_spec.rb', <<~SPEC)
|
829
|
+
describe 'h_describe' do
|
830
|
+
it 'H1 test example' do
|
831
|
+
expect(1).to eq 1
|
832
|
+
end
|
833
|
+
end
|
834
|
+
SPEC
|
835
|
+
|
836
|
+
generate_specs(spec_helper, rspec_options, [
|
837
|
+
[spec_a, spec_b],
|
838
|
+
[spec_c, failing_spec_d],
|
839
|
+
[spec_e, spec_f],
|
840
|
+
[failing_spec_g, spec_h],
|
841
|
+
])
|
842
|
+
|
843
|
+
actual = subject
|
844
|
+
|
845
|
+
expect(actual.stdout).to include('Tests in batches in before_subset_queue: [["spec_integration/a_spec.rb", "spec_integration/b_spec.rb"]]')
|
846
|
+
expect(actual.stdout).to include('Tests in batches in before_subset_queue: [["spec_integration/a_spec.rb", "spec_integration/b_spec.rb"], ["spec_integration/c_spec.rb", "spec_integration/d_spec.rb"]]')
|
847
|
+
expect(actual.stdout).to include('Tests in batches in before_subset_queue: [["spec_integration/a_spec.rb", "spec_integration/b_spec.rb"], ["spec_integration/c_spec.rb", "spec_integration/d_spec.rb"], ["spec_integration/e_spec.rb", "spec_integration/f_spec.rb"]]')
|
848
|
+
expect(actual.stdout).to include('Tests in batches in before_subset_queue: [["spec_integration/a_spec.rb", "spec_integration/b_spec.rb"], ["spec_integration/c_spec.rb", "spec_integration/d_spec.rb"], ["spec_integration/e_spec.rb", "spec_integration/f_spec.rb"], ["spec_integration/g_spec.rb", "spec_integration/h_spec.rb"]]')
|
849
|
+
|
850
|
+
expect(actual.stdout).to include('Tests in batches in after_subset_queue: [["spec_integration/a_spec.rb", "spec_integration/b_spec.rb"]]')
|
851
|
+
expect(actual.stdout).to include('Tests in batches in after_subset_queue: [["spec_integration/a_spec.rb", "spec_integration/b_spec.rb"], ["spec_integration/c_spec.rb", "spec_integration/d_spec.rb"]]')
|
852
|
+
expect(actual.stdout).to include('Tests in batches in after_subset_queue: [["spec_integration/a_spec.rb", "spec_integration/b_spec.rb"], ["spec_integration/c_spec.rb", "spec_integration/d_spec.rb"], ["spec_integration/e_spec.rb", "spec_integration/f_spec.rb"]]')
|
853
|
+
expect(actual.stdout).to include('Tests in batches in after_subset_queue: [["spec_integration/a_spec.rb", "spec_integration/b_spec.rb"], ["spec_integration/c_spec.rb", "spec_integration/d_spec.rb"], ["spec_integration/e_spec.rb", "spec_integration/f_spec.rb"], ["spec_integration/g_spec.rb", "spec_integration/h_spec.rb"]]')
|
854
|
+
|
855
|
+
|
856
|
+
expect(actual.stdout).to include("Batches' statuses in before_subset_queue: [:not_executed]")
|
857
|
+
expect(actual.stdout).to include("Batches' statuses in before_subset_queue: [:passed, :not_executed]")
|
858
|
+
expect(actual.stdout).to include("Batches' statuses in before_subset_queue: [:passed, :failed, :not_executed]")
|
859
|
+
expect(actual.stdout).to include("Batches' statuses in before_subset_queue: [:passed, :failed, :passed, :not_executed]")
|
860
|
+
|
861
|
+
expect(actual.stdout).to include("Batches' statuses in after_subset_queue: [:passed]")
|
862
|
+
expect(actual.stdout).to include("Batches' statuses in after_subset_queue: [:passed, :failed]")
|
863
|
+
expect(actual.stdout).to include("Batches' statuses in after_subset_queue: [:passed, :failed, :passed]")
|
864
|
+
expect(actual.stdout).to include("Batches' statuses in after_subset_queue: [:passed, :failed, :passed, :failed]")
|
865
|
+
|
866
|
+
expect(actual.stdout).to include('Current batch tests: ["spec_integration/a_spec.rb", "spec_integration/b_spec.rb"]')
|
867
|
+
expect(actual.stdout).to include('Current batch tests: ["spec_integration/c_spec.rb", "spec_integration/d_spec.rb"]')
|
868
|
+
expect(actual.stdout).to include('Current batch tests: ["spec_integration/e_spec.rb", "spec_integration/f_spec.rb"]')
|
869
|
+
expect(actual.stdout).to include('Current batch tests: ["spec_integration/g_spec.rb", "spec_integration/h_spec.rb"]')
|
870
|
+
expect(actual.stdout).to include('Current batch status: passed').twice
|
871
|
+
expect(actual.stdout).to include('Current batch status: failed').twice
|
872
|
+
|
873
|
+
expect(actual.exit_code).to eq 1
|
874
|
+
end
|
742
875
|
end
|
743
876
|
|
744
877
|
context 'when the RSpec seed is used' do
|
@@ -17,6 +17,40 @@ describe KnapsackPro::Config::Env do
|
|
17
17
|
|
18
18
|
it { should eq 4 }
|
19
19
|
end
|
20
|
+
|
21
|
+
context 'when both KNAPSACK_PRO_CI_NODE_TOTAL and CI environment have value' do
|
22
|
+
let(:logger) { instance_double(Logger, info: nil) }
|
23
|
+
|
24
|
+
before do
|
25
|
+
stub_const("ENV", { 'KNAPSACK_PRO_CI_NODE_TOTAL' => env_value })
|
26
|
+
expect(described_class).to receive(:ci_env_for).with(:node_total).and_return(ci_value)
|
27
|
+
allow(KnapsackPro).to receive(:logger).and_return(logger)
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when values are different' do
|
31
|
+
let(:env_value) { '5' }
|
32
|
+
let(:ci_value) { 4 }
|
33
|
+
|
34
|
+
it { should eq 5 }
|
35
|
+
|
36
|
+
it 'logs a warning' do
|
37
|
+
expect(logger).to receive(:info).with(
|
38
|
+
'You have set the environment variable KNAPSACK_PRO_CI_NODE_TOTAL to 5 which could be automatically determined from the CI environment as 4.'
|
39
|
+
)
|
40
|
+
subject
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'when values are the same' do
|
45
|
+
let(:env_value) { '5' }
|
46
|
+
let(:ci_value) { 5 }
|
47
|
+
|
48
|
+
it 'does not log a warning' do
|
49
|
+
expect(logger).not_to receive(:info)
|
50
|
+
subject
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
20
54
|
end
|
21
55
|
|
22
56
|
context "when ENV doesn't exist" do
|
@@ -41,6 +75,40 @@ describe KnapsackPro::Config::Env do
|
|
41
75
|
it { should eq 2 }
|
42
76
|
end
|
43
77
|
|
78
|
+
context 'when both KNAPSACK_PRO_CI_NODE_INDEX and CI environment have value' do
|
79
|
+
let(:logger) { instance_double(Logger, info: nil) }
|
80
|
+
|
81
|
+
before do
|
82
|
+
stub_const("ENV", { 'KNAPSACK_PRO_CI_NODE_INDEX' => env_value })
|
83
|
+
expect(described_class).to receive(:ci_env_for).with(:node_index).and_return(ci_value)
|
84
|
+
allow(KnapsackPro).to receive(:logger).and_return(logger)
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'when values are different' do
|
88
|
+
let(:env_value) { '3' }
|
89
|
+
let(:ci_value) { 2 }
|
90
|
+
|
91
|
+
it { should eq 3 }
|
92
|
+
|
93
|
+
it 'logs a warning' do
|
94
|
+
expect(logger).to receive(:info).with(
|
95
|
+
'You have set the environment variable KNAPSACK_PRO_CI_NODE_INDEX to 3 which could be automatically determined from the CI environment as 2.'
|
96
|
+
)
|
97
|
+
subject
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'when values are the same' do
|
102
|
+
let(:env_value) { '3' }
|
103
|
+
let(:ci_value) { 3 }
|
104
|
+
|
105
|
+
it 'does not log a warning' do
|
106
|
+
expect(logger).not_to receive(:info)
|
107
|
+
subject
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
44
112
|
context 'when order of loading envs does matter' do
|
45
113
|
context 'when GitLab CI' do
|
46
114
|
before { stub_const("ENV", { 'CI_NODE_INDEX' => '2', 'GITLAB_CI' => 'true' }) }
|
@@ -70,6 +138,40 @@ describe KnapsackPro::Config::Env do
|
|
70
138
|
|
71
139
|
it { should eq '8' }
|
72
140
|
end
|
141
|
+
|
142
|
+
context 'when both KNAPSACK_PRO_CI_NODE_BUILD_ID and CI environment have value' do
|
143
|
+
let(:logger) { instance_double(Logger, info: nil) }
|
144
|
+
|
145
|
+
before do
|
146
|
+
stub_const("ENV", { 'KNAPSACK_PRO_CI_NODE_BUILD_ID' => env_value })
|
147
|
+
expect(described_class).to receive(:ci_env_for).with(:node_build_id).and_return(ci_value)
|
148
|
+
allow(KnapsackPro).to receive(:logger).and_return(logger)
|
149
|
+
end
|
150
|
+
|
151
|
+
context 'when values are different' do
|
152
|
+
let(:env_value) { '7' }
|
153
|
+
let(:ci_value) { '8' }
|
154
|
+
|
155
|
+
it { should eq '7' }
|
156
|
+
|
157
|
+
it 'logs a warning' do
|
158
|
+
expect(logger).to receive(:info).with(
|
159
|
+
'You have set the environment variable KNAPSACK_PRO_CI_NODE_BUILD_ID to 7 which could be automatically determined from the CI environment as 8.'
|
160
|
+
)
|
161
|
+
subject
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
context 'when values are the same' do
|
166
|
+
let(:env_value) { '7' }
|
167
|
+
let(:ci_value) { '7' }
|
168
|
+
|
169
|
+
it 'does not log a warning' do
|
170
|
+
expect(logger).not_to receive(:info)
|
171
|
+
subject
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
73
175
|
end
|
74
176
|
|
75
177
|
context "when ENV does not exist" do
|
@@ -95,6 +197,40 @@ describe KnapsackPro::Config::Env do
|
|
95
197
|
|
96
198
|
it { should eq 2 }
|
97
199
|
end
|
200
|
+
|
201
|
+
context 'when both KNAPSACK_PRO_CI_NODE_RETRY_COUNT and CI environment have value' do
|
202
|
+
let(:logger) { instance_double(Logger, info: nil) }
|
203
|
+
|
204
|
+
before do
|
205
|
+
stub_const("ENV", { 'KNAPSACK_PRO_CI_NODE_RETRY_COUNT' => env_value })
|
206
|
+
expect(described_class).to receive(:ci_env_for).with(:node_retry_count).and_return(ci_value)
|
207
|
+
allow(KnapsackPro).to receive(:logger).and_return(logger)
|
208
|
+
end
|
209
|
+
|
210
|
+
context 'when values are different' do
|
211
|
+
let(:env_value) { '1' }
|
212
|
+
let(:ci_value) { 2 }
|
213
|
+
|
214
|
+
it { should eq 1 }
|
215
|
+
|
216
|
+
it 'logs a warning' do
|
217
|
+
expect(logger).to receive(:info).with(
|
218
|
+
'You have set the environment variable KNAPSACK_PRO_CI_NODE_RETRY_COUNT to 1 which could be automatically determined from the CI environment as 2.'
|
219
|
+
)
|
220
|
+
subject
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
context 'when values are the same' do
|
225
|
+
let(:env_value) { '7' }
|
226
|
+
let(:ci_value) { '7' }
|
227
|
+
|
228
|
+
it 'does not log a warning' do
|
229
|
+
expect(logger).not_to receive(:info)
|
230
|
+
subject
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
98
234
|
end
|
99
235
|
|
100
236
|
context "when ENV doesn't exist" do
|
@@ -131,6 +267,40 @@ describe KnapsackPro::Config::Env do
|
|
131
267
|
|
132
268
|
it { should eq 'fe61a08118d0d52e97c38666eba1eaf3' }
|
133
269
|
end
|
270
|
+
|
271
|
+
context 'when both KNAPSACK_PRO_COMMIT_HASH and CI environment have value' do
|
272
|
+
let(:logger) { instance_double(Logger, info: nil) }
|
273
|
+
|
274
|
+
before do
|
275
|
+
stub_const("ENV", { 'KNAPSACK_PRO_COMMIT_HASH' => env_value })
|
276
|
+
expect(described_class).to receive(:ci_env_for).with(:commit_hash).and_return(ci_value)
|
277
|
+
allow(KnapsackPro).to receive(:logger).and_return(logger)
|
278
|
+
end
|
279
|
+
|
280
|
+
context 'when values are different' do
|
281
|
+
let(:env_value) { '3fa64859337f6e56409d49f865d13fd7' }
|
282
|
+
let(:ci_value) { 'fe61a08118d0d52e97c38666eba1eaf3' }
|
283
|
+
|
284
|
+
it { should eq '3fa64859337f6e56409d49f865d13fd7' }
|
285
|
+
|
286
|
+
it 'logs a warning' do
|
287
|
+
expect(logger).to receive(:info).with(
|
288
|
+
'You have set the environment variable KNAPSACK_PRO_COMMIT_HASH to 3fa64859337f6e56409d49f865d13fd7 which could be automatically determined from the CI environment as fe61a08118d0d52e97c38666eba1eaf3.'
|
289
|
+
)
|
290
|
+
subject
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
context 'when values are the same' do
|
295
|
+
let(:env_value) { '3fa64859337f6e56409d49f865d13fd7' }
|
296
|
+
let(:ci_value) { '3fa64859337f6e56409d49f865d13fd7' }
|
297
|
+
|
298
|
+
it 'does not log a warning' do
|
299
|
+
expect(logger).not_to receive(:info)
|
300
|
+
subject
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
134
304
|
end
|
135
305
|
|
136
306
|
context "when ENV doesn't exist" do
|
@@ -154,6 +324,40 @@ describe KnapsackPro::Config::Env do
|
|
154
324
|
|
155
325
|
it { should eq 'feature-branch' }
|
156
326
|
end
|
327
|
+
|
328
|
+
context 'when both KNAPSACK_PRO_BRANCH and CI environment have value' do
|
329
|
+
let(:logger) { instance_double(Logger, info: nil) }
|
330
|
+
|
331
|
+
before do
|
332
|
+
stub_const("ENV", { 'KNAPSACK_PRO_BRANCH' => env_value })
|
333
|
+
expect(described_class).to receive(:ci_env_for).with(:branch).and_return(ci_value)
|
334
|
+
allow(KnapsackPro).to receive(:logger).and_return(logger)
|
335
|
+
end
|
336
|
+
|
337
|
+
context 'when values are different' do
|
338
|
+
let(:env_value) { 'master' }
|
339
|
+
let(:ci_value) { 'feature-branch' }
|
340
|
+
|
341
|
+
it { should eq 'master' }
|
342
|
+
|
343
|
+
it 'logs a warning' do
|
344
|
+
expect(logger).to receive(:info).with(
|
345
|
+
'You have set the environment variable KNAPSACK_PRO_BRANCH to master which could be automatically determined from the CI environment as feature-branch.'
|
346
|
+
)
|
347
|
+
subject
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
context 'when values are the same' do
|
352
|
+
let(:env_value) { 'master' }
|
353
|
+
let(:ci_value) { 'master' }
|
354
|
+
|
355
|
+
it 'does not log a warning' do
|
356
|
+
expect(logger).not_to receive(:info)
|
357
|
+
subject
|
358
|
+
end
|
359
|
+
end
|
360
|
+
end
|
157
361
|
end
|
158
362
|
|
159
363
|
context "when ENV doesn't exist" do
|
@@ -177,6 +381,40 @@ describe KnapsackPro::Config::Env do
|
|
177
381
|
|
178
382
|
it { should eq '/home/runner/myapp' }
|
179
383
|
end
|
384
|
+
|
385
|
+
context 'when both KNAPSACK_PRO_PROJECT_DIR and CI environment have value' do
|
386
|
+
let(:logger) { instance_double(Logger, info: nil) }
|
387
|
+
|
388
|
+
before do
|
389
|
+
stub_const("ENV", { 'KNAPSACK_PRO_PROJECT_DIR' => env_value })
|
390
|
+
expect(described_class).to receive(:ci_env_for).with(:project_dir).and_return(ci_value)
|
391
|
+
allow(KnapsackPro).to receive(:logger).and_return(logger)
|
392
|
+
end
|
393
|
+
|
394
|
+
context 'when values are different' do
|
395
|
+
let(:env_value) { '/home/user/myapp' }
|
396
|
+
let(:ci_value) { '/home/runner/myapp' }
|
397
|
+
|
398
|
+
it { should eq '/home/user/myapp' }
|
399
|
+
|
400
|
+
it 'logs a warning' do
|
401
|
+
expect(logger).to receive(:info).with(
|
402
|
+
'You have set the environment variable KNAPSACK_PRO_PROJECT_DIR to /home/user/myapp which could be automatically determined from the CI environment as /home/runner/myapp.'
|
403
|
+
)
|
404
|
+
subject
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
context 'when values are the same' do
|
409
|
+
let(:env_value) { '/home/user/myapp' }
|
410
|
+
let(:ci_value) { '/home/user/myapp' }
|
411
|
+
|
412
|
+
it 'does not log a warning' do
|
413
|
+
expect(logger).not_to receive(:info)
|
414
|
+
subject
|
415
|
+
end
|
416
|
+
end
|
417
|
+
end
|
180
418
|
end
|
181
419
|
|
182
420
|
context "when ENV doesn't exist" do
|
@@ -200,6 +438,40 @@ describe KnapsackPro::Config::Env do
|
|
200
438
|
|
201
439
|
it { should eq 'Jane Doe' }
|
202
440
|
end
|
441
|
+
|
442
|
+
context 'when both KNAPSACK_PRO_USER_SEAT and CI environment have value' do
|
443
|
+
let(:logger) { instance_double(Logger, info: nil) }
|
444
|
+
|
445
|
+
before do
|
446
|
+
stub_const("ENV", { 'KNAPSACK_PRO_USER_SEAT' => env_value })
|
447
|
+
expect(described_class).to receive(:ci_env_for).with(:user_seat).and_return(ci_value)
|
448
|
+
allow(KnapsackPro).to receive(:logger).and_return(logger)
|
449
|
+
end
|
450
|
+
|
451
|
+
context 'when values are different' do
|
452
|
+
let(:env_value) { 'John Doe' }
|
453
|
+
let(:ci_value) { 'Jane Doe' }
|
454
|
+
|
455
|
+
it { should eq 'John Doe' }
|
456
|
+
|
457
|
+
it 'logs a warning' do
|
458
|
+
expect(logger).to receive(:info).with(
|
459
|
+
'You have set the environment variable KNAPSACK_PRO_USER_SEAT to John Doe which could be automatically determined from the CI environment as Jane Doe.'
|
460
|
+
)
|
461
|
+
subject
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
465
|
+
context 'when values are the same' do
|
466
|
+
let(:env_value) { 'John Doe' }
|
467
|
+
let(:ci_value) { 'John Doe' }
|
468
|
+
|
469
|
+
it 'does not log a warning' do
|
470
|
+
expect(logger).not_to receive(:info)
|
471
|
+
subject
|
472
|
+
end
|
473
|
+
end
|
474
|
+
end
|
203
475
|
end
|
204
476
|
|
205
477
|
context "when ENV doesn't exist" do
|
@@ -345,7 +617,6 @@ describe KnapsackPro::Config::Env do
|
|
345
617
|
end
|
346
618
|
end
|
347
619
|
|
348
|
-
|
349
620
|
describe '.regular_mode?' do
|
350
621
|
subject { described_class.regular_mode? }
|
351
622
|
|
@@ -645,11 +916,18 @@ describe KnapsackPro::Config::Env do
|
|
645
916
|
['Unsupported CI', {}],
|
646
917
|
].each do |ci, env|
|
647
918
|
it "on #{ci} it is false" do
|
919
|
+
stub_const("ENV", env.merge({ 'KNAPSACK_PRO_FIXED_QUEUE_SPLIT' => 'false' }))
|
920
|
+
|
648
921
|
logger = instance_double(Logger)
|
649
922
|
allow(KnapsackPro).to receive(:logger).and_return(logger)
|
650
|
-
|
651
|
-
|
652
|
-
|
923
|
+
ci_env = described_class.detected_ci.new.fixed_queue_split
|
924
|
+
if ci_env == false
|
925
|
+
expect(logger).not_to receive(:info)
|
926
|
+
else
|
927
|
+
expect(logger).to receive(:info).with(
|
928
|
+
'You have set the environment variable KNAPSACK_PRO_FIXED_QUEUE_SPLIT to false which could be automatically determined from the CI environment as true.'
|
929
|
+
)
|
930
|
+
end
|
653
931
|
|
654
932
|
expect(subject).to eq(false)
|
655
933
|
end
|
@@ -673,11 +951,18 @@ describe KnapsackPro::Config::Env do
|
|
673
951
|
['Unsupported CI', {}],
|
674
952
|
].each do |ci, env|
|
675
953
|
it "on #{ci} it is true" do
|
954
|
+
stub_const("ENV", env.merge({ 'KNAPSACK_PRO_FIXED_QUEUE_SPLIT' => 'true' }))
|
955
|
+
|
676
956
|
logger = instance_double(Logger)
|
677
957
|
allow(KnapsackPro).to receive(:logger).and_return(logger)
|
678
|
-
|
679
|
-
|
680
|
-
|
958
|
+
ci_env = described_class.detected_ci.new.fixed_queue_split
|
959
|
+
if ci_env == true
|
960
|
+
expect(logger).not_to receive(:info)
|
961
|
+
else
|
962
|
+
expect(logger).to receive(:info).with(
|
963
|
+
'You have set the environment variable KNAPSACK_PRO_FIXED_QUEUE_SPLIT to true which could be automatically determined from the CI environment as false.'
|
964
|
+
)
|
965
|
+
end
|
681
966
|
|
682
967
|
expect(subject).to eq(true)
|
683
968
|
end
|
@@ -702,12 +987,12 @@ describe KnapsackPro::Config::Env do
|
|
702
987
|
['Unsupported CI', {}, true],
|
703
988
|
].each do |ci, env, expected|
|
704
989
|
it "on #{ci} it is #{expected}" do
|
990
|
+
stub_const("ENV", env)
|
991
|
+
|
705
992
|
logger = instance_double(Logger)
|
706
993
|
expect(KnapsackPro).to receive(:logger).and_return(logger)
|
707
994
|
expect(logger).to receive(:info).with("KNAPSACK_PRO_FIXED_QUEUE_SPLIT is not set. Using default value: #{expected}. Learn more at #{KnapsackPro::Urls::FIXED_QUEUE_SPLIT}")
|
708
995
|
|
709
|
-
stub_const("ENV", env)
|
710
|
-
|
711
996
|
expect(subject).to eq(expected)
|
712
997
|
end
|
713
998
|
end
|
@@ -2,34 +2,32 @@ describe KnapsackPro::Hooks::Queue do
|
|
2
2
|
describe '.call_before_queue' do
|
3
3
|
subject { described_class.call_before_queue }
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
end
|
5
|
+
before do
|
6
|
+
described_class.reset_before_queue
|
7
|
+
end
|
9
8
|
|
9
|
+
context 'when no callback is set' do
|
10
10
|
it { should be_nil }
|
11
11
|
end
|
12
12
|
|
13
|
-
context 'when
|
13
|
+
context 'when multiple callbacks are set' do
|
14
14
|
let(:queue_id) { double }
|
15
15
|
|
16
|
-
|
16
|
+
it 'calls each block' do
|
17
17
|
expect(KnapsackPro::Config::Env).to receive(:queue_id).twice.and_return(queue_id)
|
18
18
|
|
19
|
-
|
19
|
+
expected_called_blocks = []
|
20
20
|
|
21
21
|
described_class.before_queue do |q_id|
|
22
|
-
|
22
|
+
expected_called_blocks << [:block_1_called, q_id]
|
23
23
|
end
|
24
24
|
described_class.before_queue do |q_id|
|
25
|
-
|
25
|
+
expected_called_blocks << [:block_2_called, q_id]
|
26
26
|
end
|
27
|
-
end
|
28
27
|
|
29
|
-
it 'each block is called' do
|
30
28
|
subject
|
31
29
|
|
32
|
-
expect(
|
30
|
+
expect(expected_called_blocks).to eq([
|
33
31
|
[:block_1_called, queue_id],
|
34
32
|
[:block_2_called, queue_id],
|
35
33
|
])
|
@@ -40,114 +38,158 @@ describe KnapsackPro::Hooks::Queue do
|
|
40
38
|
describe '.call_before_subset_queue' do
|
41
39
|
subject { described_class.call_before_subset_queue }
|
42
40
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
end
|
41
|
+
before do
|
42
|
+
described_class.reset_before_subset_queue
|
43
|
+
end
|
47
44
|
|
45
|
+
context 'when no callback is set' do
|
48
46
|
it { should be_nil }
|
49
47
|
end
|
50
48
|
|
51
|
-
context 'when
|
49
|
+
context 'when multiple callbacks are set' do
|
52
50
|
let(:queue_id) { double }
|
53
51
|
let(:subset_queue_id) { double }
|
54
52
|
|
55
|
-
|
53
|
+
it 'calls each block' do
|
56
54
|
expect(KnapsackPro::Config::Env).to receive(:queue_id).twice.and_return(queue_id)
|
57
55
|
expect(KnapsackPro::Config::Env).to receive(:subset_queue_id).twice.and_return(subset_queue_id)
|
58
56
|
|
59
|
-
|
57
|
+
expected_called_blocks = []
|
60
58
|
|
61
59
|
described_class.before_subset_queue do |q_id, subset_q_id|
|
62
|
-
|
60
|
+
expected_called_blocks << [:block_1_called, q_id, subset_q_id]
|
63
61
|
end
|
64
62
|
described_class.before_subset_queue do |q_id, subset_q_id|
|
65
|
-
|
63
|
+
expected_called_blocks << [:block_2_called, q_id, subset_q_id]
|
66
64
|
end
|
67
|
-
end
|
68
65
|
|
69
|
-
it 'each block is called' do
|
70
66
|
subject
|
71
67
|
|
72
|
-
expect(
|
68
|
+
expect(expected_called_blocks).to eq([
|
73
69
|
[:block_1_called, queue_id, subset_queue_id],
|
74
70
|
[:block_2_called, queue_id, subset_queue_id],
|
75
71
|
])
|
76
72
|
end
|
77
73
|
end
|
74
|
+
|
75
|
+
context 'when a callback is set AND the queue is passed' do
|
76
|
+
let(:queue_id) { double }
|
77
|
+
let(:subset_queue_id) { double }
|
78
|
+
let(:queue) { instance_double(KnapsackPro::Queue) }
|
79
|
+
|
80
|
+
subject { described_class.call_before_subset_queue(queue) }
|
81
|
+
|
82
|
+
it 'calls each block' do
|
83
|
+
expect(KnapsackPro::Config::Env).to receive(:queue_id).and_return(queue_id)
|
84
|
+
expect(KnapsackPro::Config::Env).to receive(:subset_queue_id).and_return(subset_queue_id)
|
85
|
+
|
86
|
+
expected_called_blocks = []
|
87
|
+
|
88
|
+
described_class.before_subset_queue do |q_id, subset_q_id, queue|
|
89
|
+
expected_called_blocks << [:block_1_called, q_id, subset_q_id, queue]
|
90
|
+
end
|
91
|
+
|
92
|
+
subject
|
93
|
+
|
94
|
+
expect(expected_called_blocks).to eq([
|
95
|
+
[:block_1_called, queue_id, subset_queue_id, queue],
|
96
|
+
])
|
97
|
+
end
|
98
|
+
end
|
78
99
|
end
|
79
100
|
|
80
101
|
describe '.call_after_subset_queue' do
|
81
102
|
subject { described_class.call_after_subset_queue }
|
82
103
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
end
|
104
|
+
before do
|
105
|
+
described_class.reset_after_subset_queue
|
106
|
+
end
|
87
107
|
|
108
|
+
context 'when no callback is set' do
|
88
109
|
it { should be_nil }
|
89
110
|
end
|
90
111
|
|
91
|
-
context 'when
|
112
|
+
context 'when multiple callbacks are set' do
|
92
113
|
let(:queue_id) { double }
|
93
114
|
let(:subset_queue_id) { double }
|
94
115
|
|
95
|
-
|
116
|
+
it 'calls each block' do
|
96
117
|
expect(KnapsackPro::Config::Env).to receive(:queue_id).at_least(:once).and_return(queue_id)
|
97
118
|
expect(KnapsackPro::Config::Env).to receive(:subset_queue_id).at_least(:once).and_return(subset_queue_id)
|
98
119
|
|
99
|
-
|
120
|
+
expected_called_blocks = []
|
100
121
|
|
101
122
|
described_class.after_subset_queue do |q_id, subset_q_id|
|
102
|
-
|
123
|
+
expected_called_blocks << [:block_1_called, q_id, subset_q_id]
|
103
124
|
end
|
104
125
|
described_class.after_subset_queue do |q_id, subset_q_id|
|
105
|
-
|
126
|
+
expected_called_blocks << [:block_2_called, q_id, subset_q_id]
|
106
127
|
end
|
107
|
-
end
|
108
128
|
|
109
|
-
it 'each block is called' do
|
110
129
|
subject
|
111
130
|
|
112
|
-
expect(
|
131
|
+
expect(expected_called_blocks).to eq([
|
113
132
|
[:block_1_called, queue_id, subset_queue_id],
|
114
133
|
[:block_2_called, queue_id, subset_queue_id],
|
115
134
|
])
|
116
135
|
end
|
117
136
|
end
|
137
|
+
|
138
|
+
context 'when a callback is set AND the queue is passed' do
|
139
|
+
let(:queue_id) { double }
|
140
|
+
let(:subset_queue_id) { double }
|
141
|
+
let(:queue) { instance_double(KnapsackPro::Queue) }
|
142
|
+
|
143
|
+
subject { described_class.call_after_subset_queue(queue) }
|
144
|
+
|
145
|
+
it 'calls each block' do
|
146
|
+
expect(KnapsackPro::Config::Env).to receive(:queue_id).and_return(queue_id)
|
147
|
+
expect(KnapsackPro::Config::Env).to receive(:subset_queue_id).and_return(subset_queue_id)
|
148
|
+
|
149
|
+
expected_called_blocks = []
|
150
|
+
|
151
|
+
described_class.after_subset_queue do |q_id, subset_q_id, queue|
|
152
|
+
expected_called_blocks << [:block_1_called, q_id, subset_q_id, queue]
|
153
|
+
end
|
154
|
+
|
155
|
+
subject
|
156
|
+
|
157
|
+
expect(expected_called_blocks).to eq([
|
158
|
+
[:block_1_called, queue_id, subset_queue_id, queue],
|
159
|
+
])
|
160
|
+
end
|
161
|
+
end
|
118
162
|
end
|
119
163
|
|
120
164
|
describe '.call_after_queue' do
|
121
165
|
subject { described_class.call_after_queue }
|
122
166
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
end
|
167
|
+
before do
|
168
|
+
described_class.reset_after_queue
|
169
|
+
end
|
127
170
|
|
171
|
+
context 'when no callback is set' do
|
128
172
|
it { should be_nil }
|
129
173
|
end
|
130
174
|
|
131
|
-
context 'when
|
175
|
+
context 'when multiple callbacks are set' do
|
132
176
|
let(:queue_id) { double }
|
133
177
|
|
134
|
-
|
178
|
+
it 'calls each block' do
|
135
179
|
expect(KnapsackPro::Config::Env).to receive(:queue_id).twice.and_return(queue_id)
|
136
180
|
|
137
|
-
|
181
|
+
expected_called_blocks = []
|
138
182
|
|
139
183
|
described_class.after_queue do |q_id|
|
140
|
-
|
184
|
+
expected_called_blocks << [:block_1_called, q_id]
|
141
185
|
end
|
142
186
|
described_class.after_queue do |q_id|
|
143
|
-
|
187
|
+
expected_called_blocks << [:block_2_called, q_id]
|
144
188
|
end
|
145
|
-
end
|
146
189
|
|
147
|
-
it 'each block is called' do
|
148
190
|
subject
|
149
191
|
|
150
|
-
expect(
|
192
|
+
expect(expected_called_blocks).to eq([
|
151
193
|
[:block_1_called, queue_id],
|
152
194
|
[:block_2_called, queue_id],
|
153
195
|
])
|
@@ -0,0 +1,35 @@
|
|
1
|
+
describe KnapsackPro::Queue do
|
2
|
+
it 'simulates a Queue Mode build' do
|
3
|
+
queue = described_class.new
|
4
|
+
|
5
|
+
expect(queue.current_batch).to be_nil
|
6
|
+
|
7
|
+
# 1st batch
|
8
|
+
test_files_paths_1 = ['a_spec.rb', 'b_spec.rb']
|
9
|
+
queue.add_batch_for(test_files_paths_1)
|
10
|
+
|
11
|
+
expect(queue.current_batch.test_file_paths).to eq(['a_spec.rb', 'b_spec.rb'])
|
12
|
+
expect(queue.current_batch.status).to eq :not_executed
|
13
|
+
queue.mark_batch_passed
|
14
|
+
expect(queue.current_batch.status).to eq :passed
|
15
|
+
|
16
|
+
|
17
|
+
# 2nd batch
|
18
|
+
test_files_paths_2 = ['c_spec.rb', 'd_spec.rb']
|
19
|
+
queue.add_batch_for(test_files_paths_2)
|
20
|
+
|
21
|
+
expect(queue.current_batch.test_file_paths).to eq(['c_spec.rb', 'd_spec.rb'])
|
22
|
+
expect(queue.current_batch.status).to eq :not_executed
|
23
|
+
queue.mark_batch_failed
|
24
|
+
expect(queue.current_batch.status).to eq :failed
|
25
|
+
|
26
|
+
|
27
|
+
# last batch from the Queue API is always empty
|
28
|
+
test_files_paths_3 = []
|
29
|
+
queue.add_batch_for(test_files_paths_3)
|
30
|
+
|
31
|
+
expect(queue.size).to eq 2
|
32
|
+
expect(queue[0].status).to eq :passed
|
33
|
+
expect(queue[1].status).to eq :failed
|
34
|
+
end
|
35
|
+
end
|
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: 7.
|
4
|
+
version: 7.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ArturT
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-05-
|
11
|
+
date: 2024-05-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -214,6 +214,7 @@ files:
|
|
214
214
|
- lib/knapsack_pro/allocator.rb
|
215
215
|
- lib/knapsack_pro/allocator_builder.rb
|
216
216
|
- lib/knapsack_pro/base_allocator_builder.rb
|
217
|
+
- lib/knapsack_pro/batch.rb
|
217
218
|
- lib/knapsack_pro/build_distribution_fetcher.rb
|
218
219
|
- lib/knapsack_pro/client/api/action.rb
|
219
220
|
- lib/knapsack_pro/client/api/v1/base.rb
|
@@ -250,6 +251,7 @@ files:
|
|
250
251
|
- lib/knapsack_pro/mask_string.rb
|
251
252
|
- lib/knapsack_pro/presenter.rb
|
252
253
|
- lib/knapsack_pro/pure/queue/rspec_pure.rb
|
254
|
+
- lib/knapsack_pro/queue.rb
|
253
255
|
- lib/knapsack_pro/queue_allocator.rb
|
254
256
|
- lib/knapsack_pro/queue_allocator_builder.rb
|
255
257
|
- lib/knapsack_pro/railtie.rb
|
@@ -348,6 +350,7 @@ files:
|
|
348
350
|
- spec/knapsack_pro/pure/queue/rspec_pure_spec.rb
|
349
351
|
- spec/knapsack_pro/queue_allocator_builder_spec.rb
|
350
352
|
- spec/knapsack_pro/queue_allocator_spec.rb
|
353
|
+
- spec/knapsack_pro/queue_spec.rb
|
351
354
|
- spec/knapsack_pro/report_spec.rb
|
352
355
|
- spec/knapsack_pro/repository_adapter_initiator_spec.rb
|
353
356
|
- spec/knapsack_pro/repository_adapters/base_adapter_spec.rb
|
@@ -412,7 +415,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
412
415
|
- !ruby/object:Gem::Version
|
413
416
|
version: '0'
|
414
417
|
requirements: []
|
415
|
-
rubygems_version: 3.
|
418
|
+
rubygems_version: 3.5.6
|
416
419
|
signing_key:
|
417
420
|
specification_version: 4
|
418
421
|
summary: Knapsack Pro splits tests across parallel CI nodes and ensures each parallel
|
@@ -471,6 +474,7 @@ test_files:
|
|
471
474
|
- spec/knapsack_pro/pure/queue/rspec_pure_spec.rb
|
472
475
|
- spec/knapsack_pro/queue_allocator_builder_spec.rb
|
473
476
|
- spec/knapsack_pro/queue_allocator_spec.rb
|
477
|
+
- spec/knapsack_pro/queue_spec.rb
|
474
478
|
- spec/knapsack_pro/report_spec.rb
|
475
479
|
- spec/knapsack_pro/repository_adapter_initiator_spec.rb
|
476
480
|
- spec/knapsack_pro/repository_adapters/base_adapter_spec.rb
|