knapsack_pro 7.11.0 → 7.12.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 +9 -0
- data/CHANGELOG.md +9 -0
- data/lib/knapsack_pro/base_allocator_builder.rb +5 -0
- data/lib/knapsack_pro/config/env.rb +8 -0
- data/lib/knapsack_pro/slow_test_file_determiner.rb +6 -2
- data/lib/knapsack_pro/version.rb +1 -1
- data/spec/integration/runners/queue/rspec_runner_spec.rb +15 -0
- data/spec/knapsack_pro/base_allocator_builder_spec.rb +36 -18
- data/spec/knapsack_pro/config/env_spec.rb +31 -0
- data/spec/knapsack_pro/slow_test_file_determiner_spec.rb +25 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b6e9369d803759d8590a88b3e34bc3e195ca6520ee6f97e41c312735a768a8bb
|
4
|
+
data.tar.gz: 45dd6b4b8871cd370ec44384b706a0445cce6276b0463bc307d36f79dea16deb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a0a3f3301f24a840845b0a59d40f06aa94d1ce94d1156846f740f237606c54a05b32da7d44ee815a65674c35ca94ac63185b0d93262570c3379e60a3686872f
|
7
|
+
data.tar.gz: 12f877a2c3e060580c3b2f20fc1de7fb934c47c82f1dfa95a1b240ab82838cf6580c9325fbba494849e14515634084cc12b294224412e2e63d5aa36810572d98
|
data/.circleci/config.yml
CHANGED
@@ -268,6 +268,15 @@ jobs:
|
|
268
268
|
export KNAPSACK_PRO_FIXED_QUEUE_SPLIT=true
|
269
269
|
export KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES=true
|
270
270
|
bundle exec rake knapsack_pro:queue:rspec
|
271
|
+
- run:
|
272
|
+
working_directory: ~/rails-app-with-knapsack_pro
|
273
|
+
command: |
|
274
|
+
# split by test examples above the slow test file threshold ||
|
275
|
+
export KNAPSACK_PRO_BRANCH="$CIRCLE_BRANCH--$CIRCLE_BUILD_NUM--queue--split-above-slow-test-file-threshold"
|
276
|
+
export KNAPSACK_PRO_FIXED_QUEUE_SPLIT=true
|
277
|
+
export KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES=true
|
278
|
+
export KNAPSACK_PRO_SLOW_TEST_FILE_THRESHOLD=1
|
279
|
+
bundle exec rake knapsack_pro:queue:rspec
|
271
280
|
- run:
|
272
281
|
working_directory: ~/rails-app-with-knapsack_pro
|
273
282
|
command: |
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
### 7.12.0
|
4
|
+
|
5
|
+
* Add `KNAPSACK_PRO_SLOW_TEST_FILE_THRESHOLD` to improve the RSpec split by examples feature with many skipped tests
|
6
|
+
* Do not split test files by test cases if you run tests on a single CI node to run Knapsack Pro faster.
|
7
|
+
|
8
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/pull/282
|
9
|
+
|
10
|
+
https://github.com/KnapsackPro/knapsack_pro-ruby/compare/v7.11.0...v7.12.0
|
11
|
+
|
3
12
|
### 7.11.0
|
4
13
|
|
5
14
|
* fix(RSpec split by examples): Properly determine slow test files when test example execution times and full test file execution time are both known
|
@@ -36,6 +36,11 @@ module KnapsackPro
|
|
36
36
|
test_files_to_run = all_test_files_to_run
|
37
37
|
|
38
38
|
if adapter_class.split_by_test_cases_enabled?
|
39
|
+
if KnapsackPro::Config::Env.ci_node_total < 2
|
40
|
+
KnapsackPro.logger.warn('Skipping split of test files by test cases because you are running tests on a single CI node (no parallelism)')
|
41
|
+
return test_files_to_run
|
42
|
+
end
|
43
|
+
|
39
44
|
slow_test_files = get_slow_test_files
|
40
45
|
return test_files_to_run if slow_test_files.empty?
|
41
46
|
|
@@ -200,6 +200,14 @@ module KnapsackPro
|
|
200
200
|
ENV.fetch('KNAPSACK_PRO_RSPEC_TEST_EXAMPLE_DETECTOR_PREFIX', 'bundle exec')
|
201
201
|
end
|
202
202
|
|
203
|
+
def slow_test_file_threshold
|
204
|
+
ENV.fetch('KNAPSACK_PRO_SLOW_TEST_FILE_THRESHOLD', nil)&.to_f
|
205
|
+
end
|
206
|
+
|
207
|
+
def slow_test_file_threshold?
|
208
|
+
!!slow_test_file_threshold
|
209
|
+
end
|
210
|
+
|
203
211
|
def test_suite_token
|
204
212
|
env_name = 'KNAPSACK_PRO_TEST_SUITE_TOKEN'
|
205
213
|
ENV[env_name] || raise("Missing environment variable #{env_name}. You should set environment variable like #{env_name}_RSPEC (note there is suffix _RSPEC at the end). knapsack_pro gem will set #{env_name} based on #{env_name}_RSPEC value. If you use other test runner than RSpec then use proper suffix.")
|
@@ -10,8 +10,12 @@ module KnapsackPro
|
|
10
10
|
time_threshold = (total_execution_time / KnapsackPro::Config::Env.ci_node_total) * TIME_THRESHOLD_PER_CI_NODE
|
11
11
|
|
12
12
|
test_files.select do |test_file|
|
13
|
-
|
14
|
-
|
13
|
+
execution_time = test_file.fetch('time_execution')
|
14
|
+
next false if execution_time.zero?
|
15
|
+
next true if execution_time >= time_threshold
|
16
|
+
next false unless KnapsackPro::Config::Env.slow_test_file_threshold?
|
17
|
+
|
18
|
+
execution_time >= KnapsackPro::Config::Env.slow_test_file_threshold
|
15
19
|
end
|
16
20
|
end
|
17
21
|
|
data/lib/knapsack_pro/version.rb
CHANGED
@@ -1964,10 +1964,13 @@ describe "#{KnapsackPro::Runners::Queue::RSpecRunner} - Integration tests", :cle
|
|
1964
1964
|
# remember to stub Queue API batches to include test examples (example: a_spec.rb[1:1])
|
1965
1965
|
# for the following slow test files
|
1966
1966
|
ENV['KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN'] = "#{SPEC_DIRECTORY}/a_spec.rb"
|
1967
|
+
|
1968
|
+
ENV['KNAPSACK_PRO_CI_NODE_TOTAL'] = '2'
|
1967
1969
|
end
|
1968
1970
|
after do
|
1969
1971
|
ENV.delete('KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES')
|
1970
1972
|
ENV.delete('KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN')
|
1973
|
+
ENV.delete('KNAPSACK_PRO_CI_NODE_TOTAL')
|
1971
1974
|
end
|
1972
1975
|
|
1973
1976
|
it 'splits slow test files by examples AND ensures the test examples are executed only once' do
|
@@ -2060,10 +2063,13 @@ describe "#{KnapsackPro::Runners::Queue::RSpecRunner} - Integration tests", :cle
|
|
2060
2063
|
# remember to stub Queue API batches to include test examples (example: a_spec.rb[1:1])
|
2061
2064
|
# for the following slow test files
|
2062
2065
|
ENV['KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN'] = "#{SPEC_DIRECTORY}/a_spec.rb"
|
2066
|
+
|
2067
|
+
ENV['KNAPSACK_PRO_CI_NODE_TOTAL'] = '2'
|
2063
2068
|
end
|
2064
2069
|
after do
|
2065
2070
|
ENV.delete('KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES')
|
2066
2071
|
ENV.delete('KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN')
|
2072
|
+
ENV.delete('KNAPSACK_PRO_CI_NODE_TOTAL')
|
2067
2073
|
end
|
2068
2074
|
|
2069
2075
|
it 'sets 1 as exit code AND raises an error (a test example path as a_spec.rb[1:1] would always be executed even when it does not have the tag that is set via the --tag option. We cannot run tests because it could lead to running unintentional tests)' do
|
@@ -2138,10 +2144,13 @@ describe "#{KnapsackPro::Runners::Queue::RSpecRunner} - Integration tests", :cle
|
|
2138
2144
|
# remember to stub Queue API batches to include test examples (example: a_spec.rb[1:1])
|
2139
2145
|
# for the following slow test files
|
2140
2146
|
ENV['KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN'] = "#{SPEC_DIRECTORY}/a_spec.rb"
|
2147
|
+
|
2148
|
+
ENV['KNAPSACK_PRO_CI_NODE_TOTAL'] = '2'
|
2141
2149
|
end
|
2142
2150
|
after do
|
2143
2151
|
ENV.delete('KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES')
|
2144
2152
|
ENV.delete('KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN')
|
2153
|
+
ENV.delete('KNAPSACK_PRO_CI_NODE_TOTAL')
|
2145
2154
|
end
|
2146
2155
|
|
2147
2156
|
it 'produces a JSON report' do
|
@@ -2237,10 +2246,13 @@ describe "#{KnapsackPro::Runners::Queue::RSpecRunner} - Integration tests", :cle
|
|
2237
2246
|
# remember to stub Queue API batches to include test examples (example: a_spec.rb[1:1])
|
2238
2247
|
# for the following slow test files
|
2239
2248
|
ENV['KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN'] = "#{SPEC_DIRECTORY}/a_spec.rb"
|
2249
|
+
|
2250
|
+
ENV['KNAPSACK_PRO_CI_NODE_TOTAL'] = '2'
|
2240
2251
|
end
|
2241
2252
|
after do
|
2242
2253
|
ENV.delete('KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES')
|
2243
2254
|
ENV.delete('KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN')
|
2255
|
+
ENV.delete('KNAPSACK_PRO_CI_NODE_TOTAL')
|
2244
2256
|
end
|
2245
2257
|
|
2246
2258
|
it 'produces a JUnit XML report' do
|
@@ -2334,10 +2346,13 @@ describe "#{KnapsackPro::Runners::Queue::RSpecRunner} - Integration tests", :cle
|
|
2334
2346
|
# remember to stub Queue API batches to include test examples (example: a_spec.rb[1:1])
|
2335
2347
|
# for the following slow test files
|
2336
2348
|
ENV['KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN'] = "#{SPEC_DIRECTORY}/a_spec.rb"
|
2349
|
+
|
2350
|
+
ENV['KNAPSACK_PRO_CI_NODE_TOTAL'] = '2'
|
2337
2351
|
end
|
2338
2352
|
after do
|
2339
2353
|
ENV.delete('KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES')
|
2340
2354
|
ENV.delete('KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN')
|
2355
|
+
ENV.delete('KNAPSACK_PRO_CI_NODE_TOTAL')
|
2341
2356
|
end
|
2342
2357
|
|
2343
2358
|
it 'produces a code coverage report' do
|
@@ -134,39 +134,57 @@ describe KnapsackPro::BaseAllocatorBuilder do
|
|
134
134
|
|
135
135
|
before do
|
136
136
|
expect(adapter_class).to receive(:split_by_test_cases_enabled?).and_return(true)
|
137
|
+
expect(KnapsackPro::Config::Env).to receive(:ci_node_total).and_return(node_total)
|
137
138
|
|
138
139
|
test_file_pattern = double
|
139
140
|
expect(KnapsackPro::TestFilePattern).to receive(:call).with(adapter_class).and_return(test_file_pattern)
|
140
141
|
|
141
142
|
expect(KnapsackPro::TestFileFinder).to receive(:call).with(test_file_pattern).and_return(test_files_to_run)
|
143
|
+
end
|
144
|
+
|
145
|
+
context 'when less than 2 CI nodes' do
|
146
|
+
let(:node_total) { 1 }
|
142
147
|
|
143
|
-
|
148
|
+
it 'returns test files without test cases' do
|
149
|
+
logger = instance_double(Logger)
|
150
|
+
expect(KnapsackPro).to receive(:logger).and_return(logger)
|
151
|
+
expect(logger).to receive(:warn).with('Skipping split of test files by test cases because you are running tests on a single CI node (no parallelism)')
|
152
|
+
expect(subject).to eq test_files_to_run
|
153
|
+
end
|
144
154
|
end
|
145
155
|
|
146
|
-
context 'when
|
147
|
-
let(:
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
]
|
156
|
+
context 'when at least 2 CI nodes' do
|
157
|
+
let(:node_total) { 2 }
|
158
|
+
|
159
|
+
before do
|
160
|
+
expect(allocator_builder).to receive(:get_slow_test_files).and_return(slow_test_files)
|
152
161
|
end
|
153
162
|
|
154
|
-
|
155
|
-
|
156
|
-
|
163
|
+
context 'when slow test files are detected' do
|
164
|
+
let(:slow_test_files) do
|
165
|
+
[
|
166
|
+
'1_spec.rb',
|
167
|
+
'2_spec.rb',
|
168
|
+
]
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'returns test files with test cases' do
|
172
|
+
test_file_cases = double
|
173
|
+
expect(adapter_class).to receive(:test_file_cases_for).with(slow_test_files).and_return(test_file_cases)
|
157
174
|
|
158
|
-
|
159
|
-
|
175
|
+
test_files_with_test_cases = double
|
176
|
+
expect(KnapsackPro::TestFilesWithTestCasesComposer).to receive(:call).with(test_files_to_run, slow_test_files, test_file_cases).and_return(test_files_with_test_cases)
|
160
177
|
|
161
|
-
|
178
|
+
expect(subject).to eq test_files_with_test_cases
|
179
|
+
end
|
162
180
|
end
|
163
|
-
end
|
164
181
|
|
165
|
-
|
166
|
-
|
182
|
+
context 'when slow test files are not detected' do
|
183
|
+
let(:slow_test_files) { [] }
|
167
184
|
|
168
|
-
|
169
|
-
|
185
|
+
it 'returns test files without test cases' do
|
186
|
+
expect(subject).to eq test_files_to_run
|
187
|
+
end
|
170
188
|
end
|
171
189
|
end
|
172
190
|
end
|
@@ -1062,6 +1062,37 @@ describe KnapsackPro::Config::Env do
|
|
1062
1062
|
end
|
1063
1063
|
end
|
1064
1064
|
|
1065
|
+
describe '.slow_test_file_threshold' do
|
1066
|
+
subject { described_class.slow_test_file_threshold }
|
1067
|
+
|
1068
|
+
context 'when ENV exists' do
|
1069
|
+
before { stub_const("ENV", { 'KNAPSACK_PRO_SLOW_TEST_FILE_THRESHOLD' => '2' }) }
|
1070
|
+
it 'returns seconds' do
|
1071
|
+
expect(subject).to eq 2.0
|
1072
|
+
expect(subject).to be_a Float
|
1073
|
+
end
|
1074
|
+
end
|
1075
|
+
|
1076
|
+
context "when ENV doesn't exist" do
|
1077
|
+
before { stub_const("ENV", {}) }
|
1078
|
+
it { should be_nil }
|
1079
|
+
end
|
1080
|
+
end
|
1081
|
+
|
1082
|
+
describe '.slow_test_file_threshold?' do
|
1083
|
+
subject { described_class.slow_test_file_threshold? }
|
1084
|
+
|
1085
|
+
context 'when ENV exists' do
|
1086
|
+
before { stub_const("ENV", { 'KNAPSACK_PRO_SLOW_TEST_FILE_THRESHOLD' => '2' }) }
|
1087
|
+
it { should be true }
|
1088
|
+
end
|
1089
|
+
|
1090
|
+
context "when ENV doesn't exist" do
|
1091
|
+
before { stub_const("ENV", {}) }
|
1092
|
+
it { should be false }
|
1093
|
+
end
|
1094
|
+
end
|
1095
|
+
|
1065
1096
|
describe '.test_suite_token' do
|
1066
1097
|
subject { described_class.test_suite_token }
|
1067
1098
|
|
@@ -8,8 +8,7 @@ describe KnapsackPro::SlowTestFileDeterminer do
|
|
8
8
|
|
9
9
|
subject { described_class.call(test_files) }
|
10
10
|
|
11
|
-
context 'when test files have recorded time
|
12
|
-
let(:time_execution) { 20.0 }
|
11
|
+
context 'when test files have recorded execution time' do
|
13
12
|
let(:test_files) do
|
14
13
|
[
|
15
14
|
{ 'path' => 'a_spec.rb', 'time_execution' => 1.0 },
|
@@ -27,7 +26,30 @@ describe KnapsackPro::SlowTestFileDeterminer do
|
|
27
26
|
end
|
28
27
|
end
|
29
28
|
|
30
|
-
context 'when test files have
|
29
|
+
context 'when test files have recorded execution time AND slow test files threshold is set' do
|
30
|
+
let(:test_files) do
|
31
|
+
[
|
32
|
+
{ 'path' => 'a_spec.rb', 'time_execution' => 1.0 },
|
33
|
+
{ 'path' => 'b_spec.rb', 'time_execution' => 3.4 },
|
34
|
+
{ 'path' => 'c_spec.rb', 'time_execution' => 3.5 },
|
35
|
+
{ 'path' => 'd_spec.rb', 'time_execution' => 12.1 },
|
36
|
+
]
|
37
|
+
end
|
38
|
+
|
39
|
+
before do
|
40
|
+
stub_const("ENV", { 'KNAPSACK_PRO_SLOW_TEST_FILE_THRESHOLD' => '2' })
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'detects slow tests above 2.0s threshold' do
|
44
|
+
expect(subject).to eq([
|
45
|
+
{ 'path' => 'b_spec.rb', 'time_execution' => 3.4 },
|
46
|
+
{ 'path' => 'c_spec.rb', 'time_execution' => 3.5 },
|
47
|
+
{ 'path' => 'd_spec.rb', 'time_execution' => 12.1 },
|
48
|
+
])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'when test files have no recorded execution time' do
|
31
53
|
let(:test_files) do
|
32
54
|
[
|
33
55
|
{ 'path' => 'a_spec.rb', 'time_execution' => 0.0 },
|
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.12.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-10-
|
11
|
+
date: 2024-10-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|