knapsack_pro 7.11.0 → 7.12.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/.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
|