knapsack_pro 3.8.0 → 7.0.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 +377 -23
- data/.github/dependabot.yml +11 -0
- data/.github/pull_request_template.md +22 -0
- data/.gitignore +4 -0
- data/CHANGELOG.md +325 -1
- data/Gemfile +9 -0
- data/README.md +3 -10
- data/bin/test +15 -0
- data/knapsack_pro.gemspec +7 -6
- data/lib/knapsack_pro/adapters/base_adapter.rb +17 -2
- data/lib/knapsack_pro/adapters/cucumber_adapter.rb +3 -3
- data/lib/knapsack_pro/adapters/minitest_adapter.rb +2 -0
- data/lib/knapsack_pro/adapters/rspec_adapter.rb +88 -49
- data/lib/knapsack_pro/adapters/spinach_adapter.rb +2 -0
- data/lib/knapsack_pro/adapters/test_unit_adapter.rb +2 -0
- data/lib/knapsack_pro/allocator.rb +2 -0
- data/lib/knapsack_pro/allocator_builder.rb +2 -0
- data/lib/knapsack_pro/base_allocator_builder.rb +8 -25
- data/lib/knapsack_pro/build_distribution_fetcher.rb +2 -0
- data/lib/knapsack_pro/client/api/action.rb +2 -0
- data/lib/knapsack_pro/client/api/v1/base.rb +2 -0
- data/lib/knapsack_pro/client/api/v1/build_distributions.rb +5 -0
- data/lib/knapsack_pro/client/api/v1/build_subsets.rb +2 -0
- data/lib/knapsack_pro/client/api/v1/queues.rb +6 -1
- data/lib/knapsack_pro/client/connection.rb +5 -6
- data/lib/knapsack_pro/config/ci/app_veyor.rb +18 -0
- data/lib/knapsack_pro/config/ci/base.rb +27 -0
- data/lib/knapsack_pro/config/ci/buildkite.rb +18 -0
- data/lib/knapsack_pro/config/ci/circle.rb +18 -0
- data/lib/knapsack_pro/config/ci/cirrus_ci.rb +18 -0
- data/lib/knapsack_pro/config/ci/codefresh.rb +18 -0
- data/lib/knapsack_pro/config/ci/codeship.rb +18 -0
- data/lib/knapsack_pro/config/ci/github_actions.rb +26 -0
- data/lib/knapsack_pro/config/ci/gitlab_ci.rb +20 -1
- data/lib/knapsack_pro/config/ci/heroku.rb +18 -0
- data/lib/knapsack_pro/config/ci/semaphore.rb +16 -0
- data/lib/knapsack_pro/config/ci/semaphore2.rb +19 -0
- data/lib/knapsack_pro/config/ci/travis.rb +18 -0
- data/lib/knapsack_pro/config/env.rb +46 -22
- data/lib/knapsack_pro/config/env_generator.rb +2 -0
- data/lib/knapsack_pro/config/temp_files.rb +8 -4
- data/lib/knapsack_pro/crypto/branch_encryptor.rb +2 -0
- data/lib/knapsack_pro/crypto/decryptor.rb +2 -0
- data/lib/knapsack_pro/crypto/digestor.rb +2 -0
- data/lib/knapsack_pro/crypto/encryptor.rb +2 -0
- data/lib/knapsack_pro/extensions/rspec_extension.rb +137 -0
- data/lib/knapsack_pro/formatters/rspec_json_formatter.rb +2 -0
- data/lib/knapsack_pro/formatters/time_tracker.rb +152 -0
- data/lib/knapsack_pro/formatters/time_tracker_fetcher.rb +20 -0
- data/lib/knapsack_pro/hooks/queue.rb +2 -0
- data/lib/knapsack_pro/logger_wrapper.rb +2 -0
- data/lib/knapsack_pro/mask_string.rb +9 -0
- data/lib/knapsack_pro/presenter.rb +6 -3
- data/lib/knapsack_pro/pure/queue/rspec_pure.rb +92 -0
- data/lib/knapsack_pro/queue_allocator.rb +2 -0
- data/lib/knapsack_pro/queue_allocator_builder.rb +2 -0
- data/lib/knapsack_pro/railtie.rb +2 -0
- data/lib/knapsack_pro/report.rb +15 -9
- data/lib/knapsack_pro/repository_adapter_initiator.rb +2 -0
- data/lib/knapsack_pro/repository_adapters/base_adapter.rb +2 -0
- data/lib/knapsack_pro/repository_adapters/env_adapter.rb +2 -0
- data/lib/knapsack_pro/repository_adapters/git_adapter.rb +50 -0
- data/lib/knapsack_pro/runners/base_runner.rb +2 -0
- data/lib/knapsack_pro/runners/cucumber_runner.rb +2 -0
- data/lib/knapsack_pro/runners/minitest_runner.rb +2 -0
- data/lib/knapsack_pro/runners/queue/base_runner.rb +29 -0
- data/lib/knapsack_pro/runners/queue/cucumber_runner.rb +9 -6
- data/lib/knapsack_pro/runners/queue/minitest_runner.rb +13 -6
- data/lib/knapsack_pro/runners/queue/rspec_runner.rb +128 -135
- data/lib/knapsack_pro/runners/rspec_runner.rb +22 -3
- data/lib/knapsack_pro/runners/spinach_runner.rb +2 -0
- data/lib/knapsack_pro/runners/test_unit_runner.rb +2 -0
- data/lib/knapsack_pro/slow_test_file_determiner.rb +2 -0
- data/lib/knapsack_pro/slow_test_file_finder.rb +2 -0
- data/lib/knapsack_pro/task_loader.rb +2 -0
- data/lib/knapsack_pro/test_case_detectors/rspec_test_example_detector.rb +2 -0
- data/lib/knapsack_pro/test_case_mergers/base_merger.rb +2 -0
- data/lib/knapsack_pro/test_case_mergers/rspec_merger.rb +2 -0
- data/lib/knapsack_pro/test_file_cleaner.rb +2 -0
- data/lib/knapsack_pro/test_file_finder.rb +2 -0
- data/lib/knapsack_pro/test_file_pattern.rb +2 -0
- data/lib/knapsack_pro/test_file_presenter.rb +2 -0
- data/lib/knapsack_pro/test_files_with_test_cases_composer.rb +2 -0
- data/lib/knapsack_pro/test_flat_distributor.rb +2 -0
- data/lib/knapsack_pro/tracker.rb +3 -3
- data/lib/knapsack_pro/urls.rb +4 -0
- data/lib/knapsack_pro/utils.rb +2 -0
- data/lib/knapsack_pro/version.rb +3 -1
- data/lib/knapsack_pro.rb +5 -3
- data/lib/tasks/cucumber.rake +2 -0
- data/lib/tasks/encrypted_branch_names.rake +2 -0
- data/lib/tasks/encrypted_test_file_names.rake +2 -0
- data/lib/tasks/minitest.rake +2 -0
- data/lib/tasks/queue/cucumber.rake +13 -0
- data/lib/tasks/queue/minitest.rake +13 -0
- data/lib/tasks/queue/rspec.rake +13 -0
- data/lib/tasks/rspec.rake +5 -0
- data/lib/tasks/salt.rake +2 -0
- data/lib/tasks/spinach.rake +2 -0
- data/lib/tasks/test_unit.rake +2 -0
- data/spec/integration/api/build_distributions_subset_spec.rb +1 -0
- data/spec/integration/runners/queue/rspec_runner.rb +80 -0
- data/spec/integration/runners/queue/rspec_runner_spec.rb +2232 -0
- data/spec/knapsack_pro/adapters/base_adapter_spec.rb +30 -11
- data/spec/knapsack_pro/adapters/cucumber_adapter_spec.rb +2 -5
- data/spec/knapsack_pro/adapters/rspec_adapter_spec.rb +146 -174
- data/spec/knapsack_pro/base_allocator_builder_spec.rb +22 -48
- data/spec/knapsack_pro/client/api/v1/build_distributions_spec.rb +19 -27
- data/spec/knapsack_pro/client/api/v1/queues_spec.rb +23 -43
- data/spec/knapsack_pro/client/connection_spec.rb +59 -7
- data/spec/knapsack_pro/config/ci/app_veyor_spec.rb +22 -8
- data/spec/knapsack_pro/config/ci/base_spec.rb +1 -0
- data/spec/knapsack_pro/config/ci/buildkite_spec.rb +51 -16
- data/spec/knapsack_pro/config/ci/circle_spec.rb +48 -13
- data/spec/knapsack_pro/config/ci/cirrus_ci_spec.rb +12 -12
- data/spec/knapsack_pro/config/ci/codefresh_spec.rb +21 -6
- data/spec/knapsack_pro/config/ci/codeship_spec.rb +20 -6
- data/spec/knapsack_pro/config/ci/github_actions_spec.rb +37 -10
- data/spec/knapsack_pro/config/ci/gitlab_ci_spec.rb +48 -13
- data/spec/knapsack_pro/config/ci/heroku_spec.rb +12 -12
- data/spec/knapsack_pro/config/ci/semaphore2_spec.rb +11 -11
- data/spec/knapsack_pro/config/ci/semaphore_spec.rb +12 -12
- data/spec/knapsack_pro/config/ci/travis_spec.rb +8 -8
- data/spec/knapsack_pro/config/env_spec.rb +204 -124
- data/spec/knapsack_pro/formatters/time_tracker_specs.rb +424 -0
- data/spec/knapsack_pro/hooks/queue_spec.rb +2 -2
- data/spec/knapsack_pro/presenter_spec.rb +1 -1
- data/spec/knapsack_pro/pure/queue/rspec_pure_spec.rb +224 -0
- data/spec/knapsack_pro/repository_adapters/git_adapter_spec.rb +72 -0
- data/spec/knapsack_pro/runners/queue/cucumber_runner_spec.rb +18 -16
- data/spec/knapsack_pro/runners/queue/minitest_runner_spec.rb +17 -14
- data/spec/knapsack_pro/runners/rspec_runner_spec.rb +40 -23
- data/spec/knapsack_pro/test_case_detectors/rspec_test_example_detector_spec.rb +1 -0
- data/spec/knapsack_pro/tracker_spec.rb +0 -4
- data/spec/knapsack_pro_spec.rb +3 -3
- data/spec/spec_helper.rb +0 -1
- metadata +26 -23
- data/lib/knapsack_pro/config/ci/snap_ci.rb +0 -35
- data/lib/knapsack_pro/config/ci/solano_ci.rb +0 -32
- data/lib/knapsack_pro/extensions/time.rb +0 -7
- data/lib/knapsack_pro/formatters/rspec_queue_profile_formatter_extension.rb +0 -56
- data/lib/knapsack_pro/formatters/rspec_queue_summary_formatter.rb +0 -112
- data/spec/knapsack_pro/config/ci/snap_ci_spec.rb +0 -104
- data/spec/knapsack_pro/config/ci/solano_ci_spec.rb +0 -73
- data/spec/knapsack_pro/extensions/time_spec.rb +0 -5
- data/spec/knapsack_pro/runners/queue/rspec_runner_spec.rb +0 -342
|
@@ -42,6 +42,18 @@ describe KnapsackPro::Adapters::BaseAdapter do
|
|
|
42
42
|
end
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
+
describe '.split_by_test_cases_enabled?' do
|
|
46
|
+
subject { described_class.split_by_test_cases_enabled? }
|
|
47
|
+
|
|
48
|
+
it { expect(subject).to be false }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe '.test_file_cases_for' do
|
|
52
|
+
subject { described_class.test_file_cases_for([]) }
|
|
53
|
+
|
|
54
|
+
it { expect { subject }.to raise_error NotImplementedError }
|
|
55
|
+
end
|
|
56
|
+
|
|
45
57
|
describe '.slow_test_file?' do
|
|
46
58
|
let(:adapter_class) { double }
|
|
47
59
|
let(:slow_test_files) do
|
|
@@ -98,6 +110,7 @@ describe KnapsackPro::Adapters::BaseAdapter do
|
|
|
98
110
|
|
|
99
111
|
before do
|
|
100
112
|
expect(::Kernel).to receive(:at_exit).and_yield
|
|
113
|
+
allow(File).to receive(:exist?)
|
|
101
114
|
expect(File).to receive(:exist?).with('.knapsack_pro/KnapsackPro-Adapters-BaseAdapter-bind_method_called_for_node_0.txt').and_return(adapter_bind_method_called_file_exists)
|
|
102
115
|
end
|
|
103
116
|
|
|
@@ -146,7 +159,7 @@ describe KnapsackPro::Adapters::BaseAdapter do
|
|
|
146
159
|
it do
|
|
147
160
|
logger = instance_double(Logger)
|
|
148
161
|
expect(KnapsackPro).to receive(:logger).and_return(logger)
|
|
149
|
-
expect(logger).to receive(:debug).with('
|
|
162
|
+
expect(logger).to receive(:debug).with('Regular Mode enabled.')
|
|
150
163
|
end
|
|
151
164
|
it { expect(subject).to receive(:bind_time_tracker) }
|
|
152
165
|
it { expect(subject).to receive(:bind_save_report) }
|
|
@@ -155,24 +168,22 @@ describe KnapsackPro::Adapters::BaseAdapter do
|
|
|
155
168
|
context 'when queue recording enabled' do
|
|
156
169
|
let(:queue_recording_enabled?) { true }
|
|
157
170
|
|
|
158
|
-
before do
|
|
159
|
-
allow(subject).to receive(:bind_before_queue_hook)
|
|
160
|
-
allow(subject).to receive(:bind_time_tracker)
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
it do
|
|
171
|
+
it 'calls queue hooks in proper order before binding time tracker' do
|
|
164
172
|
logger = instance_double(Logger)
|
|
165
173
|
expect(KnapsackPro).to receive(:logger).and_return(logger)
|
|
166
|
-
expect(logger).to receive(:debug).with('
|
|
174
|
+
expect(logger).to receive(:debug).with('Queue Mode enabled.')
|
|
175
|
+
|
|
176
|
+
expect(subject).to receive(:bind_before_queue_hook).ordered
|
|
177
|
+
expect(subject).to receive(:bind_after_queue_hook).ordered
|
|
178
|
+
expect(subject).to receive(:bind_time_tracker).ordered
|
|
167
179
|
end
|
|
168
|
-
it { expect(subject).to receive(:bind_before_queue_hook) }
|
|
169
|
-
it { expect(subject).to receive(:bind_time_tracker) }
|
|
170
180
|
end
|
|
171
181
|
|
|
172
182
|
context 'when recording disabled' do
|
|
173
|
-
it { expect(subject).not_to receive(:bind_time_tracker) }
|
|
174
183
|
it { expect(subject).not_to receive(:bind_save_report) }
|
|
175
184
|
it { expect(subject).not_to receive(:bind_before_queue_hook) }
|
|
185
|
+
it { expect(subject).not_to receive(:bind_after_queue_hook) }
|
|
186
|
+
it { expect(subject).not_to receive(:bind_time_tracker) }
|
|
176
187
|
end
|
|
177
188
|
end
|
|
178
189
|
|
|
@@ -199,4 +210,12 @@ describe KnapsackPro::Adapters::BaseAdapter do
|
|
|
199
210
|
}.to raise_error(NotImplementedError)
|
|
200
211
|
end
|
|
201
212
|
end
|
|
213
|
+
|
|
214
|
+
describe '#bind_after_queue_hook' do
|
|
215
|
+
it do
|
|
216
|
+
expect {
|
|
217
|
+
subject.bind_after_queue_hook
|
|
218
|
+
}.to raise_error(NotImplementedError)
|
|
219
|
+
end
|
|
220
|
+
end
|
|
202
221
|
end
|
|
@@ -203,16 +203,13 @@ describe KnapsackPro::Adapters::CucumberAdapter do
|
|
|
203
203
|
end
|
|
204
204
|
end
|
|
205
205
|
|
|
206
|
-
describe '#
|
|
206
|
+
describe '#bind_after_queue_hook' do
|
|
207
207
|
it do
|
|
208
|
-
expect(subject).to receive(:bind_before_queue_hook)
|
|
209
|
-
expect(subject).to receive(:bind_time_tracker)
|
|
210
|
-
|
|
211
208
|
expect(::Kernel).to receive(:at_exit).and_yield
|
|
212
209
|
expect(KnapsackPro::Hooks::Queue).to receive(:call_after_subset_queue)
|
|
213
210
|
expect(KnapsackPro::Report).to receive(:save_subset_queue_to_file)
|
|
214
211
|
|
|
215
|
-
subject.
|
|
212
|
+
subject.bind_after_queue_hook
|
|
216
213
|
end
|
|
217
214
|
end
|
|
218
215
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require_relative '../../../lib/knapsack_pro/formatters/time_tracker'
|
|
2
|
+
|
|
1
3
|
describe KnapsackPro::Adapters::RSpecAdapter do
|
|
2
4
|
it 'backwards compatibility with knapsack gem old rspec adapter name' do
|
|
3
5
|
expect(KnapsackPro::Adapters::RspecAdapter.new).to be_kind_of(described_class)
|
|
@@ -8,10 +10,85 @@ describe KnapsackPro::Adapters::RSpecAdapter do
|
|
|
8
10
|
end
|
|
9
11
|
|
|
10
12
|
context do
|
|
11
|
-
before { expect(::RSpec).to receive(:configure) }
|
|
13
|
+
before { expect(::RSpec).to receive(:configure).at_least(:once) }
|
|
12
14
|
it_behaves_like 'adapter'
|
|
13
15
|
end
|
|
14
16
|
|
|
17
|
+
describe '.split_by_test_cases_enabled?' do
|
|
18
|
+
subject { described_class.split_by_test_cases_enabled? }
|
|
19
|
+
|
|
20
|
+
before do
|
|
21
|
+
expect(KnapsackPro::Config::Env).to receive(:rspec_split_by_test_examples?).and_return(rspec_split_by_test_examples_enabled)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context 'when the RSpec split by test examples is enabled' do
|
|
25
|
+
let(:rspec_split_by_test_examples_enabled) { true }
|
|
26
|
+
|
|
27
|
+
it { expect(subject).to be true }
|
|
28
|
+
|
|
29
|
+
context 'when the RSpec version is < 3.3.0' do
|
|
30
|
+
before do
|
|
31
|
+
stub_const('RSpec::Core::Version::STRING', '3.2.0')
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it do
|
|
35
|
+
expect { subject }.to raise_error RuntimeError, 'RSpec >= 3.3.0 is required to split test files by test examples. Learn more: https://knapsackpro.com/perma/ruby/split-by-test-examples'
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context 'when the RSpec split by test examples is disabled' do
|
|
41
|
+
let(:rspec_split_by_test_examples_enabled) { false }
|
|
42
|
+
|
|
43
|
+
it { expect(subject).to be false }
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
describe '.test_file_cases_for' do
|
|
48
|
+
let(:slow_test_files) do
|
|
49
|
+
[
|
|
50
|
+
'1_spec.rb',
|
|
51
|
+
'2_spec.rb',
|
|
52
|
+
'3_spec.rb',
|
|
53
|
+
'4_spec.rb',
|
|
54
|
+
'5_spec.rb',
|
|
55
|
+
]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
subject { described_class.test_file_cases_for(slow_test_files) }
|
|
59
|
+
|
|
60
|
+
before do
|
|
61
|
+
logger = instance_double(Logger)
|
|
62
|
+
expect(KnapsackPro).to receive(:logger).and_return(logger)
|
|
63
|
+
expect(logger).to receive(:info).with("Generating RSpec test examples JSON report for slow test files to prepare it to be split by test examples (by individual test cases). Thanks to that, a single slow test file can be split across parallel CI nodes. Analyzing 5 slow test files.")
|
|
64
|
+
|
|
65
|
+
cmd = 'RACK_ENV=test RAILS_ENV=test bundle exec rake knapsack_pro:rspec_test_example_detector'
|
|
66
|
+
expect(Kernel).to receive(:system).with(cmd).and_return(cmd_result)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
context 'when the rake task to detect RSpec test examples succeeded' do
|
|
70
|
+
let(:cmd_result) { true }
|
|
71
|
+
|
|
72
|
+
it 'returns test example paths for slow test files' do
|
|
73
|
+
rspec_test_example_detector = instance_double(KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector)
|
|
74
|
+
expect(KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector).to receive(:new).and_return(rspec_test_example_detector)
|
|
75
|
+
|
|
76
|
+
test_file_example_paths = double
|
|
77
|
+
expect(rspec_test_example_detector).to receive(:test_file_example_paths).and_return(test_file_example_paths)
|
|
78
|
+
|
|
79
|
+
expect(subject).to eq test_file_example_paths
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
context 'when the rake task to detect RSpec test examples failed' do
|
|
84
|
+
let(:cmd_result) { false }
|
|
85
|
+
|
|
86
|
+
it do
|
|
87
|
+
expect { subject }.to raise_error(RuntimeError, 'Could not generate JSON report for RSpec. Rake task failed when running RACK_ENV=test RAILS_ENV=test bundle exec rake knapsack_pro:rspec_test_example_detector')
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
15
92
|
describe '.ensure_no_tag_option_when_rspec_split_by_test_examples_enabled!' do
|
|
16
93
|
let(:cli_args) { double }
|
|
17
94
|
|
|
@@ -162,59 +239,79 @@ describe KnapsackPro::Adapters::RSpecAdapter do
|
|
|
162
239
|
end
|
|
163
240
|
end
|
|
164
241
|
|
|
165
|
-
describe '.
|
|
166
|
-
let(:
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
242
|
+
describe '.file_path_for' do
|
|
243
|
+
let(:current_example) { ::RSpec.describe.example }
|
|
244
|
+
|
|
245
|
+
subject { described_class.file_path_for(current_example) }
|
|
246
|
+
|
|
247
|
+
context "when id ends in _spec.rb" do
|
|
248
|
+
it "returns the first part of the id" do
|
|
249
|
+
allow(current_example).to receive(:id).and_return("./foo_spec.rb[1:1]")
|
|
250
|
+
|
|
251
|
+
expect(subject).to eq('./foo_spec.rb')
|
|
252
|
+
end
|
|
176
253
|
end
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
254
|
+
|
|
255
|
+
context "when id does not end in _spec.rb" do
|
|
256
|
+
it "returns the file_path" do
|
|
257
|
+
allow(current_example).to receive(:id).and_return("./foo.rb")
|
|
258
|
+
allow(current_example).to receive(:metadata).and_return(file_path: "./foo_spec.rb")
|
|
259
|
+
|
|
260
|
+
expect(subject).to eq('./foo_spec.rb')
|
|
261
|
+
end
|
|
181
262
|
end
|
|
182
263
|
|
|
183
|
-
|
|
264
|
+
context "when id and file_path do not end in _spec.rb" do
|
|
265
|
+
it "returns the example_group's file_path" do
|
|
266
|
+
allow(current_example).to receive(:id).and_return("./foo.rb")
|
|
267
|
+
allow(current_example).to receive(:metadata).and_return(
|
|
268
|
+
file_path: "./foo.rb", example_group: { file_path: "./foo_spec.rb" }
|
|
269
|
+
)
|
|
184
270
|
|
|
185
|
-
|
|
271
|
+
expect(subject).to eq('./foo_spec.rb')
|
|
272
|
+
end
|
|
273
|
+
end
|
|
186
274
|
|
|
187
|
-
context
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
275
|
+
context "when id, file_path, and example_group's file_path do not end in _spec.rb" do
|
|
276
|
+
it "returns the top_level_group's file_path" do
|
|
277
|
+
allow(current_example).to receive(:id).and_return("./foo.rb")
|
|
278
|
+
allow(current_example).to receive(:metadata).and_return(
|
|
279
|
+
file_path: "./foo.rb",
|
|
280
|
+
example_group: {
|
|
281
|
+
file_path: "./foo.rb",
|
|
193
282
|
parent_example_group: {
|
|
194
|
-
file_path: "
|
|
283
|
+
file_path: "./foo_spec.rb",
|
|
195
284
|
}
|
|
196
285
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
before { stub_const("Turnip::VERSION", '1.2.4') }
|
|
286
|
+
)
|
|
200
287
|
|
|
201
|
-
|
|
288
|
+
expect(subject).to eq('./foo_spec.rb')
|
|
202
289
|
end
|
|
290
|
+
end
|
|
203
291
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
292
|
+
context "when id, file_path, example_group's, and top_level_group's file_path do not end in _spec.rb" do
|
|
293
|
+
it "returns empty string" do
|
|
294
|
+
allow(current_example).to receive(:id).and_return("./foo.rb")
|
|
295
|
+
allow(current_example).to receive(:metadata).and_return(
|
|
296
|
+
file_path: "./foo.rb",
|
|
297
|
+
example_group: {
|
|
298
|
+
file_path: "./foo.rb",
|
|
209
299
|
parent_example_group: {
|
|
210
|
-
file_path: "./
|
|
300
|
+
file_path: "./foo.rb",
|
|
211
301
|
}
|
|
212
302
|
}
|
|
213
|
-
|
|
303
|
+
)
|
|
214
304
|
|
|
215
|
-
|
|
305
|
+
expect(subject).to eq('')
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
context "when id does not end in .feature (nor _spec.rb)" do
|
|
310
|
+
it "returns the file_path" do
|
|
311
|
+
allow(current_example).to receive(:id).and_return("./foo.rb")
|
|
312
|
+
allow(current_example).to receive(:metadata).and_return(file_path: "./foo.feature")
|
|
216
313
|
|
|
217
|
-
|
|
314
|
+
expect(subject).to eq("./foo.feature")
|
|
218
315
|
end
|
|
219
316
|
end
|
|
220
317
|
end
|
|
@@ -223,155 +320,37 @@ describe KnapsackPro::Adapters::RSpecAdapter do
|
|
|
223
320
|
let(:config) { double }
|
|
224
321
|
|
|
225
322
|
describe '#bind_time_tracker' do
|
|
226
|
-
let(:tracker) { instance_double(KnapsackPro::Tracker) }
|
|
227
|
-
let(:logger) { instance_double(Logger) }
|
|
228
|
-
let(:global_time) { 'Global time: 01m 05s' }
|
|
229
|
-
let(:test_path) { 'spec/a_spec.rb' }
|
|
230
323
|
let(:current_example) { double(metadata: {}) }
|
|
231
324
|
|
|
232
325
|
context "when the example's metadata has :focus tag AND RSpec inclusion rule includes :focus" do
|
|
233
326
|
let(:current_example) { double(metadata: { focus: true }) }
|
|
327
|
+
let(:test_path) { 'spec/a_spec.rb' }
|
|
234
328
|
|
|
235
329
|
it do
|
|
236
|
-
expect(KnapsackPro::Config::Env).to receive(:rspec_split_by_test_examples?).and_return(false)
|
|
237
|
-
|
|
238
|
-
expect(config).to receive(:prepend_before).with(:context).and_yield
|
|
239
|
-
|
|
240
|
-
allow(KnapsackPro).to receive(:tracker).and_return(tracker)
|
|
241
|
-
expect(tracker).to receive(:start_timer).ordered
|
|
242
|
-
|
|
243
330
|
expect(config).to receive(:around).with(:each).and_yield(current_example)
|
|
244
331
|
expect(::RSpec).to receive(:configure).and_yield(config)
|
|
245
332
|
|
|
246
|
-
expect(
|
|
247
|
-
expect(tracker).to receive(:stop_timer).ordered
|
|
248
|
-
|
|
249
|
-
expect(described_class).to receive(:test_path).with(current_example).and_return(test_path)
|
|
250
|
-
|
|
251
|
-
expect(tracker).to receive(:current_test_path=).with(test_path).ordered
|
|
333
|
+
expect(described_class).to receive(:file_path_for).with(current_example).and_return(test_path)
|
|
252
334
|
|
|
253
335
|
expect(described_class).to receive_message_chain(:rspec_configuration, :filter, :rules, :[]).with(:focus).and_return(true)
|
|
254
336
|
|
|
255
337
|
expect {
|
|
256
338
|
subject.bind_time_tracker
|
|
257
|
-
}.to raise_error /
|
|
339
|
+
}.to raise_error /Knapsack Pro found an example tagged with focus in spec\/a_spec\.rb/i
|
|
258
340
|
end
|
|
259
341
|
end
|
|
260
342
|
|
|
261
|
-
context '
|
|
262
|
-
before do
|
|
263
|
-
expect(KnapsackPro::Config::Env).to receive(:rspec_split_by_test_examples?).and_return(false)
|
|
264
|
-
end
|
|
265
|
-
|
|
343
|
+
context 'with no focus' do
|
|
266
344
|
it 'records time for current test path' do
|
|
267
|
-
expect(config).to receive(:prepend_before).with(:context).and_yield
|
|
268
|
-
|
|
269
|
-
allow(KnapsackPro).to receive(:tracker).and_return(tracker)
|
|
270
|
-
expect(tracker).to receive(:start_timer).ordered
|
|
271
|
-
|
|
272
345
|
expect(config).to receive(:around).with(:each).and_yield(current_example)
|
|
273
|
-
expect(config).to receive(:append_after).with(:
|
|
274
|
-
expect(
|
|
275
|
-
expect(::RSpec).to receive(:configure).and_yield(config)
|
|
276
|
-
|
|
277
|
-
expect(tracker).to receive(:current_test_path).ordered.and_return(test_path)
|
|
278
|
-
expect(tracker).to receive(:stop_timer).ordered
|
|
279
|
-
|
|
280
|
-
expect(described_class).to receive(:test_path).with(current_example).and_return(test_path)
|
|
281
|
-
|
|
282
|
-
expect(tracker).to receive(:current_test_path=).with(test_path).ordered
|
|
346
|
+
expect(config).to receive(:append_after).with(:suite)
|
|
347
|
+
expect(::RSpec).to receive(:configure).at_least(1).and_yield(config)
|
|
283
348
|
|
|
284
349
|
expect(current_example).to receive(:run)
|
|
285
350
|
|
|
286
|
-
expect(tracker).to receive(:stop_timer).ordered
|
|
287
|
-
|
|
288
|
-
expect(KnapsackPro::Presenter).to receive(:global_time).and_return(global_time)
|
|
289
|
-
expect(KnapsackPro).to receive(:logger).and_return(logger)
|
|
290
|
-
expect(logger).to receive(:debug).with(global_time)
|
|
291
|
-
|
|
292
351
|
subject.bind_time_tracker
|
|
293
352
|
end
|
|
294
353
|
end
|
|
295
|
-
|
|
296
|
-
context 'when rspec split by test examples is enabled' do
|
|
297
|
-
let(:test_example_path) { 'spec/a_spec.rb[1:1]' }
|
|
298
|
-
|
|
299
|
-
before do
|
|
300
|
-
expect(KnapsackPro::Config::Env).to receive(:rspec_split_by_test_examples?).and_return(true)
|
|
301
|
-
end
|
|
302
|
-
|
|
303
|
-
context 'when current test_path is a slow test file' do
|
|
304
|
-
before do
|
|
305
|
-
expect(described_class).to receive(:slow_test_file?).with(described_class, test_path).and_return(true)
|
|
306
|
-
end
|
|
307
|
-
|
|
308
|
-
it 'records time for example.id' do
|
|
309
|
-
expect(current_example).to receive(:id).and_return(test_example_path)
|
|
310
|
-
|
|
311
|
-
expect(config).to receive(:prepend_before).with(:context).and_yield
|
|
312
|
-
|
|
313
|
-
allow(KnapsackPro).to receive(:tracker).and_return(tracker)
|
|
314
|
-
expect(tracker).to receive(:start_timer).ordered
|
|
315
|
-
|
|
316
|
-
expect(config).to receive(:around).with(:each).and_yield(current_example)
|
|
317
|
-
expect(config).to receive(:append_after).with(:context).and_yield
|
|
318
|
-
expect(config).to receive(:after).with(:suite).and_yield
|
|
319
|
-
expect(::RSpec).to receive(:configure).and_yield(config)
|
|
320
|
-
|
|
321
|
-
expect(tracker).to receive(:current_test_path).ordered.and_return(test_path)
|
|
322
|
-
expect(tracker).to receive(:stop_timer).ordered
|
|
323
|
-
|
|
324
|
-
expect(described_class).to receive(:test_path).with(current_example).and_return(test_path)
|
|
325
|
-
|
|
326
|
-
expect(tracker).to receive(:current_test_path=).with(test_example_path).ordered
|
|
327
|
-
|
|
328
|
-
expect(current_example).to receive(:run)
|
|
329
|
-
|
|
330
|
-
expect(tracker).to receive(:stop_timer).ordered
|
|
331
|
-
|
|
332
|
-
expect(KnapsackPro::Presenter).to receive(:global_time).and_return(global_time)
|
|
333
|
-
expect(KnapsackPro).to receive(:logger).and_return(logger)
|
|
334
|
-
expect(logger).to receive(:debug).with(global_time)
|
|
335
|
-
|
|
336
|
-
subject.bind_time_tracker
|
|
337
|
-
end
|
|
338
|
-
end
|
|
339
|
-
|
|
340
|
-
context 'when current test_path is not a slow test file' do
|
|
341
|
-
before do
|
|
342
|
-
expect(described_class).to receive(:slow_test_file?).with(described_class, test_path).and_return(false)
|
|
343
|
-
end
|
|
344
|
-
|
|
345
|
-
it 'records time for current test path' do
|
|
346
|
-
expect(config).to receive(:prepend_before).with(:context).and_yield
|
|
347
|
-
|
|
348
|
-
allow(KnapsackPro).to receive(:tracker).and_return(tracker)
|
|
349
|
-
expect(tracker).to receive(:start_timer).ordered
|
|
350
|
-
|
|
351
|
-
expect(config).to receive(:around).with(:each).and_yield(current_example)
|
|
352
|
-
expect(config).to receive(:append_after).with(:context).and_yield
|
|
353
|
-
expect(config).to receive(:after).with(:suite).and_yield
|
|
354
|
-
expect(::RSpec).to receive(:configure).and_yield(config)
|
|
355
|
-
|
|
356
|
-
expect(described_class).to receive(:test_path).with(current_example).and_return(test_path)
|
|
357
|
-
|
|
358
|
-
expect(tracker).to receive(:current_test_path).ordered.and_return(test_path)
|
|
359
|
-
expect(tracker).to receive(:stop_timer).ordered
|
|
360
|
-
|
|
361
|
-
expect(tracker).to receive(:current_test_path=).with(test_path).ordered
|
|
362
|
-
|
|
363
|
-
expect(current_example).to receive(:run)
|
|
364
|
-
|
|
365
|
-
expect(tracker).to receive(:stop_timer).ordered
|
|
366
|
-
|
|
367
|
-
expect(KnapsackPro::Presenter).to receive(:global_time).and_return(global_time)
|
|
368
|
-
expect(KnapsackPro).to receive(:logger).and_return(logger)
|
|
369
|
-
expect(logger).to receive(:debug).with(global_time)
|
|
370
|
-
|
|
371
|
-
subject.bind_time_tracker
|
|
372
|
-
end
|
|
373
|
-
end
|
|
374
|
-
end
|
|
375
354
|
end
|
|
376
355
|
|
|
377
356
|
describe '#bind_save_report' do
|
|
@@ -379,21 +358,14 @@ describe KnapsackPro::Adapters::RSpecAdapter do
|
|
|
379
358
|
expect(config).to receive(:after).with(:suite).and_yield
|
|
380
359
|
expect(::RSpec).to receive(:configure).and_yield(config)
|
|
381
360
|
|
|
382
|
-
|
|
361
|
+
time_tracker = instance_double(KnapsackPro::Formatters::TimeTracker)
|
|
362
|
+
times = [{ path: "foo_spec.rb", time_execution: 1.0 }]
|
|
363
|
+
expect(time_tracker).to receive(:batch).and_return(times)
|
|
364
|
+
expect(KnapsackPro::Formatters::TimeTrackerFetcher).to receive(:call).and_return(time_tracker)
|
|
365
|
+
expect(KnapsackPro::Report).to receive(:save).with(times)
|
|
383
366
|
|
|
384
367
|
subject.bind_save_report
|
|
385
368
|
end
|
|
386
369
|
end
|
|
387
|
-
|
|
388
|
-
describe '#bind_before_queue_hook' do
|
|
389
|
-
it do
|
|
390
|
-
expect(config).to receive(:before).with(:suite).and_yield
|
|
391
|
-
expect(::RSpec).to receive(:configure).and_yield(config)
|
|
392
|
-
|
|
393
|
-
expect(KnapsackPro::Hooks::Queue).to receive(:call_before_queue)
|
|
394
|
-
|
|
395
|
-
subject.bind_before_queue_hook
|
|
396
|
-
end
|
|
397
|
-
end
|
|
398
370
|
end
|
|
399
371
|
end
|
|
@@ -117,8 +117,8 @@ describe KnapsackPro::BaseAllocatorBuilder do
|
|
|
117
117
|
describe '#fast_and_slow_test_files_to_run' do
|
|
118
118
|
subject { allocator_builder.fast_and_slow_test_files_to_run }
|
|
119
119
|
|
|
120
|
-
context 'when
|
|
121
|
-
it do
|
|
120
|
+
context 'when split by test cases disabled' do
|
|
121
|
+
it 'returns test files to run based on test files on the disk' do
|
|
122
122
|
test_file_pattern = double
|
|
123
123
|
expect(KnapsackPro::TestFilePattern).to receive(:call).with(adapter_class).and_return(test_file_pattern)
|
|
124
124
|
|
|
@@ -129,70 +129,44 @@ describe KnapsackPro::BaseAllocatorBuilder do
|
|
|
129
129
|
end
|
|
130
130
|
end
|
|
131
131
|
|
|
132
|
-
context 'when
|
|
133
|
-
let(:adapter_class) { KnapsackPro::Adapters::RSpecAdapter }
|
|
132
|
+
context 'when split by test cases enabled' do
|
|
134
133
|
let(:test_files_to_run) { double }
|
|
135
|
-
let(:cmd) { 'RACK_ENV=test RAILS_ENV=test bundle exec rake knapsack_pro:rspec_test_example_detector' }
|
|
136
134
|
|
|
137
|
-
before
|
|
138
|
-
expect(
|
|
135
|
+
before do
|
|
136
|
+
expect(adapter_class).to receive(:split_by_test_cases_enabled?).and_return(true)
|
|
139
137
|
|
|
140
138
|
test_file_pattern = double
|
|
141
139
|
expect(KnapsackPro::TestFilePattern).to receive(:call).with(adapter_class).and_return(test_file_pattern)
|
|
142
140
|
|
|
143
141
|
expect(KnapsackPro::TestFileFinder).to receive(:call).with(test_file_pattern).and_return(test_files_to_run)
|
|
144
|
-
end
|
|
145
142
|
|
|
146
|
-
|
|
147
|
-
before do
|
|
148
|
-
stub_const('RSpec::Core::Version::STRING', '3.2.0')
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
it do
|
|
152
|
-
expect { subject }.to raise_error RuntimeError, 'RSpec >= 3.3.0 is required to split test files by test examples. Learn more: https://knapsackpro.com/perma/ruby/split-by-test-examples'
|
|
153
|
-
end
|
|
143
|
+
expect(allocator_builder).to receive(:get_slow_test_files).and_return(slow_test_files)
|
|
154
144
|
end
|
|
155
145
|
|
|
156
|
-
context 'when
|
|
157
|
-
let(:slow_test_files)
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
before do
|
|
164
|
-
expect(allocator_builder).to receive(:get_slow_test_files).and_return(slow_test_files)
|
|
165
|
-
|
|
166
|
-
expect(KnapsackPro).to receive(:logger).and_return(logger)
|
|
167
|
-
|
|
168
|
-
expect(Kernel).to receive(:system).with(cmd).and_return(cmd_result)
|
|
169
|
-
|
|
170
|
-
rspec_test_example_detector = instance_double(KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector)
|
|
171
|
-
expect(KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector).to receive(:new).and_return(rspec_test_example_detector)
|
|
172
|
-
expect(rspec_test_example_detector).to receive(:test_file_example_paths).and_return(test_file_example_paths)
|
|
173
|
-
|
|
174
|
-
expect(KnapsackPro::TestFilesWithTestCasesComposer).to receive(:call).with(test_files_to_run, slow_test_files, test_file_example_paths).and_return(test_files_with_test_cases)
|
|
146
|
+
context 'when slow test files are detected' do
|
|
147
|
+
let(:slow_test_files) do
|
|
148
|
+
[
|
|
149
|
+
'1_spec.rb',
|
|
150
|
+
'2_spec.rb',
|
|
151
|
+
]
|
|
175
152
|
end
|
|
176
153
|
|
|
177
|
-
it do
|
|
178
|
-
|
|
154
|
+
it 'returns test files with test cases' do
|
|
155
|
+
test_file_cases = double
|
|
156
|
+
expect(adapter_class).to receive(:test_file_cases_for).with(slow_test_files).and_return(test_file_cases)
|
|
157
|
+
|
|
158
|
+
test_files_with_test_cases = double
|
|
159
|
+
expect(KnapsackPro::TestFilesWithTestCasesComposer).to receive(:call).with(test_files_to_run, slow_test_files, test_file_cases).and_return(test_files_with_test_cases)
|
|
179
160
|
|
|
180
161
|
expect(subject).to eq test_files_with_test_cases
|
|
181
162
|
end
|
|
182
163
|
end
|
|
183
164
|
|
|
184
|
-
context 'when
|
|
185
|
-
let(:slow_test_files) {
|
|
186
|
-
let(:cmd_result) { false }
|
|
187
|
-
|
|
188
|
-
before do
|
|
189
|
-
expect(allocator_builder).to receive(:get_slow_test_files).and_return(slow_test_files)
|
|
190
|
-
|
|
191
|
-
expect(Kernel).to receive(:system).with(cmd).and_return(cmd_result)
|
|
192
|
-
end
|
|
165
|
+
context 'when slow test files are not detected' do
|
|
166
|
+
let(:slow_test_files) { [] }
|
|
193
167
|
|
|
194
|
-
it do
|
|
195
|
-
expect
|
|
168
|
+
it 'returns test files without test cases' do
|
|
169
|
+
expect(subject).to eq test_files_to_run
|
|
196
170
|
end
|
|
197
171
|
end
|
|
198
172
|
end
|
|
@@ -6,7 +6,9 @@ describe KnapsackPro::Client::API::V1::BuildDistributions do
|
|
|
6
6
|
let(:node_total) { double }
|
|
7
7
|
let(:node_index) { double }
|
|
8
8
|
let(:ci_build_id) { double }
|
|
9
|
+
let(:masked_user_seat) { double }
|
|
9
10
|
let(:test_files) { double }
|
|
11
|
+
let(:cache_read_attempt) { [false, true].sample }
|
|
10
12
|
|
|
11
13
|
subject do
|
|
12
14
|
described_class.subset(
|
|
@@ -22,6 +24,7 @@ describe KnapsackPro::Client::API::V1::BuildDistributions do
|
|
|
22
24
|
before do
|
|
23
25
|
expect(KnapsackPro::Config::Env).to receive(:fixed_test_suite_split).and_return(fixed_test_suite_split)
|
|
24
26
|
expect(KnapsackPro::Config::Env).to receive(:ci_node_build_id).and_return(ci_build_id)
|
|
27
|
+
expect(KnapsackPro::Config::Env).to receive(:masked_user_seat).and_return(masked_user_seat)
|
|
25
28
|
end
|
|
26
29
|
|
|
27
30
|
context 'when cache_read_attempt=true' do
|
|
@@ -29,19 +32,9 @@ describe KnapsackPro::Client::API::V1::BuildDistributions do
|
|
|
29
32
|
|
|
30
33
|
it 'does not send test_files among other params' do
|
|
31
34
|
action = double
|
|
32
|
-
expect(KnapsackPro::Client::API::Action).to receive(:new).with(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
request_hash: {
|
|
36
|
-
fixed_test_suite_split: fixed_test_suite_split,
|
|
37
|
-
cache_read_attempt: cache_read_attempt,
|
|
38
|
-
commit_hash: commit_hash,
|
|
39
|
-
branch: branch,
|
|
40
|
-
node_total: node_total,
|
|
41
|
-
node_index: node_index,
|
|
42
|
-
ci_build_id: ci_build_id,
|
|
43
|
-
}
|
|
44
|
-
}).and_return(action)
|
|
35
|
+
expect(KnapsackPro::Client::API::Action).to receive(:new).with(
|
|
36
|
+
hash_including(request_hash: hash_excluding(:test_files))
|
|
37
|
+
).and_return(action)
|
|
45
38
|
expect(subject).to eq action
|
|
46
39
|
end
|
|
47
40
|
end
|
|
@@ -51,23 +44,22 @@ describe KnapsackPro::Client::API::V1::BuildDistributions do
|
|
|
51
44
|
|
|
52
45
|
it 'sends test_files among other params' do
|
|
53
46
|
action = double
|
|
54
|
-
expect(KnapsackPro::Client::API::Action).to receive(:new).with(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
request_hash: {
|
|
58
|
-
fixed_test_suite_split: fixed_test_suite_split,
|
|
59
|
-
cache_read_attempt: cache_read_attempt,
|
|
60
|
-
commit_hash: commit_hash,
|
|
61
|
-
branch: branch,
|
|
62
|
-
node_total: node_total,
|
|
63
|
-
node_index: node_index,
|
|
64
|
-
ci_build_id: ci_build_id,
|
|
65
|
-
test_files: test_files
|
|
66
|
-
}
|
|
67
|
-
}).and_return(action)
|
|
47
|
+
expect(KnapsackPro::Client::API::Action).to receive(:new).with(
|
|
48
|
+
hash_including(request_hash: hash_including(test_files: test_files))
|
|
49
|
+
).and_return(action)
|
|
68
50
|
expect(subject).to eq action
|
|
69
51
|
end
|
|
70
52
|
end
|
|
53
|
+
|
|
54
|
+
it "sends authors" do
|
|
55
|
+
action = double
|
|
56
|
+
|
|
57
|
+
expect(KnapsackPro::Client::API::Action).to receive(:new).with(
|
|
58
|
+
hash_including(request_hash: hash_including(:build_author, :commit_authors))
|
|
59
|
+
).and_return(action)
|
|
60
|
+
|
|
61
|
+
expect(subject).to eq action
|
|
62
|
+
end
|
|
71
63
|
end
|
|
72
64
|
|
|
73
65
|
describe '.last' do
|