knapsack_pro 1.20.1 → 1.22.2
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/CHANGELOG.md +45 -0
- data/README.md +42 -17
- data/lib/knapsack_pro.rb +6 -0
- data/lib/knapsack_pro/adapters/base_adapter.rb +16 -0
- data/lib/knapsack_pro/adapters/rspec_adapter.rb +11 -9
- data/lib/knapsack_pro/allocator.rb +7 -5
- data/lib/knapsack_pro/allocator_builder.rb +2 -1
- data/lib/knapsack_pro/base_allocator_builder.rb +41 -10
- data/lib/knapsack_pro/build_distribution_fetcher.rb +57 -0
- data/lib/knapsack_pro/client/api/v1/build_distributions.rb +13 -0
- data/lib/knapsack_pro/client/connection.rb +38 -16
- data/lib/knapsack_pro/config/env.rb +4 -0
- data/lib/knapsack_pro/queue_allocator.rb +7 -5
- data/lib/knapsack_pro/queue_allocator_builder.rb +2 -1
- data/lib/knapsack_pro/report.rb +1 -1
- data/lib/knapsack_pro/runners/queue/cucumber_runner.rb +10 -1
- data/lib/knapsack_pro/runners/queue/rspec_runner.rb +7 -0
- data/lib/knapsack_pro/runners/rspec_runner.rb +5 -2
- data/lib/knapsack_pro/slow_test_file_determiner.rb +33 -0
- data/lib/knapsack_pro/slow_test_file_finder.rb +27 -0
- data/lib/knapsack_pro/test_case_detectors/rspec_test_example_detector.rb +26 -7
- data/lib/knapsack_pro/test_case_mergers/base_merger.rb +29 -0
- data/lib/knapsack_pro/test_case_mergers/rspec_merger.rb +34 -0
- data/lib/knapsack_pro/test_file_finder.rb +43 -5
- data/lib/knapsack_pro/test_files_with_test_cases_composer.rb +22 -0
- data/lib/knapsack_pro/version.rb +1 -1
- data/spec/knapsack_pro/adapters/base_adapter_spec.rb +55 -0
- data/spec/knapsack_pro/adapters/rspec_adapter_spec.rb +61 -25
- data/spec/knapsack_pro/allocator_builder_spec.rb +7 -3
- data/spec/knapsack_pro/allocator_spec.rb +7 -5
- data/spec/knapsack_pro/base_allocator_builder_spec.rb +79 -27
- data/spec/knapsack_pro/build_distribution_fetcher_spec.rb +89 -0
- data/spec/knapsack_pro/client/api/v1/build_distributions_spec.rb +31 -0
- data/spec/knapsack_pro/client/connection_spec.rb +235 -104
- data/spec/knapsack_pro/config/env_spec.rb +14 -0
- data/spec/knapsack_pro/queue_allocator_builder_spec.rb +7 -3
- data/spec/knapsack_pro/queue_allocator_spec.rb +7 -5
- data/spec/knapsack_pro/report_spec.rb +1 -1
- data/spec/knapsack_pro/runners/queue/cucumber_runner_spec.rb +38 -25
- data/spec/knapsack_pro/runners/rspec_runner_spec.rb +4 -4
- data/spec/knapsack_pro/slow_test_file_determiner_spec.rb +74 -0
- data/spec/knapsack_pro/slow_test_file_finder_spec.rb +43 -0
- data/spec/knapsack_pro/test_case_detectors/rspec_test_example_detector_spec.rb +83 -37
- data/spec/knapsack_pro/test_case_mergers/base_merger_spec.rb +27 -0
- data/spec/knapsack_pro/test_case_mergers/rspec_merger_spec.rb +59 -0
- data/spec/knapsack_pro/test_file_finder_spec.rb +105 -29
- data/spec/knapsack_pro/test_files_with_test_cases_composer_spec.rb +41 -0
- metadata +20 -2
@@ -0,0 +1,22 @@
|
|
1
|
+
module KnapsackPro
|
2
|
+
class TestFilesWithTestCasesComposer
|
3
|
+
# Args:
|
4
|
+
# All 3 arguments have structure: [{ 'path' => 'spec/a_spec.rb', 'time_execution' => 0.0 }]
|
5
|
+
# time_execution is not always present (but it's not relevant here)
|
6
|
+
#
|
7
|
+
# test_files - list of test files that you want to run tests for
|
8
|
+
# slow_test_files - list of slow test files that should be split by test cases
|
9
|
+
# test_file_cases - list of paths to test cases (test examples) inside of all slow test files (slow_test_files)
|
10
|
+
# Return:
|
11
|
+
# Test files and test cases paths (it excludes test files that should be split by test cases (test examples))
|
12
|
+
def self.call(test_files, slow_test_files, test_file_cases)
|
13
|
+
slow_test_file_paths = KnapsackPro::TestFilePresenter.paths(slow_test_files)
|
14
|
+
|
15
|
+
test_files_without_slow_test_files = test_files.reject do |test_file|
|
16
|
+
slow_test_file_paths.include?(test_file.fetch('path'))
|
17
|
+
end
|
18
|
+
|
19
|
+
test_files_without_slow_test_files + test_file_cases
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/knapsack_pro/version.rb
CHANGED
@@ -3,6 +3,61 @@ describe KnapsackPro::Adapters::BaseAdapter do
|
|
3
3
|
expect(described_class::TEST_DIR_PATTERN).to eq 'test/**{,/*/**}/*_test.rb'
|
4
4
|
end
|
5
5
|
|
6
|
+
shared_examples '.slow_test_file? method' do
|
7
|
+
context 'when test_file_path is in slow test file paths' do
|
8
|
+
# add ./ before path to ensure KnapsackPro::TestFileCleaner.clean will clean it
|
9
|
+
let(:test_file_path) { './spec/models/user_spec.rb' }
|
10
|
+
|
11
|
+
it do
|
12
|
+
expect(subject).to be true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'when test_file_path is not in slow test file paths' do
|
17
|
+
let(:test_file_path) { './spec/models/article_spec.rb' }
|
18
|
+
|
19
|
+
it do
|
20
|
+
expect(subject).to be false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '.slow_test_file?' do
|
26
|
+
let(:adapter_class) { double }
|
27
|
+
let(:slow_test_files) do
|
28
|
+
[
|
29
|
+
{ 'path' => 'spec/models/user_spec.rb' },
|
30
|
+
{ 'path' => 'spec/controllers/users_spec.rb' },
|
31
|
+
]
|
32
|
+
end
|
33
|
+
|
34
|
+
subject { described_class.slow_test_file?(adapter_class, test_file_path) }
|
35
|
+
|
36
|
+
before do
|
37
|
+
# reset class variable
|
38
|
+
described_class.instance_variable_set(:@slow_test_file_paths, nil)
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'when slow test file pattern is present' do
|
42
|
+
before do
|
43
|
+
stub_const('ENV', {
|
44
|
+
'KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN' => '{spec/models/*_spec.rb}',
|
45
|
+
})
|
46
|
+
expect(KnapsackPro::TestFileFinder).to receive(:slow_test_files_by_pattern).with(adapter_class).and_return(slow_test_files)
|
47
|
+
end
|
48
|
+
|
49
|
+
it_behaves_like '.slow_test_file? method'
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'when slow test file pattern is not present' do
|
53
|
+
before do
|
54
|
+
expect(KnapsackPro::SlowTestFileDeterminer).to receive(:read_from_json_report).and_return(slow_test_files)
|
55
|
+
end
|
56
|
+
|
57
|
+
it_behaves_like '.slow_test_file? method'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
6
61
|
describe '.bind' do
|
7
62
|
let(:adapter) { instance_double(described_class) }
|
8
63
|
|
@@ -71,22 +71,21 @@ describe KnapsackPro::Adapters::RSpecAdapter do
|
|
71
71
|
let(:tracker) { instance_double(KnapsackPro::Tracker) }
|
72
72
|
let(:logger) { instance_double(Logger) }
|
73
73
|
let(:global_time) { 'Global time: 01m 05s' }
|
74
|
+
let(:test_path) { 'spec/a_spec.rb' }
|
75
|
+
let(:example) { double }
|
76
|
+
let(:example_group) { double }
|
77
|
+
let(:current_example) do
|
78
|
+
OpenStruct.new(metadata: {
|
79
|
+
example_group: example_group
|
80
|
+
})
|
81
|
+
end
|
74
82
|
|
75
83
|
context 'when rspec split by test examples is disabled' do
|
76
|
-
let(:test_path) { 'spec/a_spec.rb' }
|
77
|
-
let(:example) { double }
|
78
|
-
let(:example_group) { double }
|
79
|
-
let(:current_example) do
|
80
|
-
OpenStruct.new(metadata: {
|
81
|
-
example_group: example_group
|
82
|
-
})
|
83
|
-
end
|
84
|
-
|
85
84
|
before do
|
86
85
|
expect(KnapsackPro::Config::Env).to receive(:rspec_split_by_test_examples?).and_return(false)
|
87
86
|
end
|
88
87
|
|
89
|
-
it do
|
88
|
+
it 'records time for current test path' do
|
90
89
|
expect(config).to receive(:around).with(:each).and_yield(example)
|
91
90
|
expect(config).to receive(:after).with(:suite).and_yield
|
92
91
|
expect(::RSpec).to receive(:configure).and_yield(config)
|
@@ -112,32 +111,69 @@ describe KnapsackPro::Adapters::RSpecAdapter do
|
|
112
111
|
|
113
112
|
context 'when rspec split by test examples is enabled' do
|
114
113
|
let(:test_example_path) { 'spec/a_spec.rb[1:1]' }
|
115
|
-
let(:example) { double }
|
116
114
|
|
117
115
|
before do
|
118
116
|
expect(KnapsackPro::Config::Env).to receive(:rspec_split_by_test_examples?).and_return(true)
|
119
117
|
end
|
120
118
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
119
|
+
context 'when current test_path is a slow test file' do
|
120
|
+
before do
|
121
|
+
expect(described_class).to receive(:slow_test_file?).with(described_class, test_path).and_return(true)
|
122
|
+
end
|
125
123
|
|
126
|
-
|
124
|
+
it 'records time for example.id' do
|
125
|
+
expect(example).to receive(:id).and_return(test_example_path)
|
127
126
|
|
128
|
-
|
129
|
-
|
130
|
-
|
127
|
+
expect(config).to receive(:around).with(:each).and_yield(example)
|
128
|
+
expect(config).to receive(:after).with(:suite).and_yield
|
129
|
+
expect(::RSpec).to receive(:configure).and_yield(config)
|
131
130
|
|
132
|
-
|
131
|
+
expect(::RSpec).to receive(:current_example).twice.and_return(current_example)
|
132
|
+
expect(described_class).to receive(:test_path).with(example_group).and_return(test_path)
|
133
133
|
|
134
|
-
|
134
|
+
allow(KnapsackPro).to receive(:tracker).and_return(tracker)
|
135
|
+
expect(tracker).to receive(:current_test_path=).with(test_example_path)
|
136
|
+
expect(tracker).to receive(:start_timer)
|
135
137
|
|
136
|
-
|
137
|
-
expect(KnapsackPro).to receive(:logger).and_return(logger)
|
138
|
-
expect(logger).to receive(:debug).with(global_time)
|
138
|
+
expect(example).to receive(:run)
|
139
139
|
|
140
|
-
|
140
|
+
expect(tracker).to receive(:stop_timer)
|
141
|
+
|
142
|
+
expect(KnapsackPro::Presenter).to receive(:global_time).and_return(global_time)
|
143
|
+
expect(KnapsackPro).to receive(:logger).and_return(logger)
|
144
|
+
expect(logger).to receive(:debug).with(global_time)
|
145
|
+
|
146
|
+
subject.bind_time_tracker
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
context 'when current test_path is not a slow test file' do
|
151
|
+
before do
|
152
|
+
expect(described_class).to receive(:slow_test_file?).with(described_class, test_path).and_return(false)
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'records time for current test path' do
|
156
|
+
expect(config).to receive(:around).with(:each).and_yield(example)
|
157
|
+
expect(config).to receive(:after).with(:suite).and_yield
|
158
|
+
expect(::RSpec).to receive(:configure).and_yield(config)
|
159
|
+
|
160
|
+
expect(::RSpec).to receive(:current_example).twice.and_return(current_example)
|
161
|
+
expect(described_class).to receive(:test_path).with(example_group).and_return(test_path)
|
162
|
+
|
163
|
+
allow(KnapsackPro).to receive(:tracker).and_return(tracker)
|
164
|
+
expect(tracker).to receive(:current_test_path=).with(test_path)
|
165
|
+
expect(tracker).to receive(:start_timer)
|
166
|
+
|
167
|
+
expect(example).to receive(:run)
|
168
|
+
|
169
|
+
expect(tracker).to receive(:stop_timer)
|
170
|
+
|
171
|
+
expect(KnapsackPro::Presenter).to receive(:global_time).and_return(global_time)
|
172
|
+
expect(KnapsackPro).to receive(:logger).and_return(logger)
|
173
|
+
expect(logger).to receive(:debug).with(global_time)
|
174
|
+
|
175
|
+
subject.bind_time_tracker
|
176
|
+
end
|
141
177
|
end
|
142
178
|
end
|
143
179
|
end
|
@@ -8,8 +8,11 @@ describe KnapsackPro::AllocatorBuilder do
|
|
8
8
|
subject { allocator_builder.allocator }
|
9
9
|
|
10
10
|
before do
|
11
|
-
|
12
|
-
expect(allocator_builder).to receive(:
|
11
|
+
fast_and_slow_test_files_to_run = double
|
12
|
+
expect(allocator_builder).to receive(:fast_and_slow_test_files_to_run).and_return(fast_and_slow_test_files_to_run)
|
13
|
+
|
14
|
+
fallback_mode_test_files = double
|
15
|
+
expect(allocator_builder).to receive(:fallback_mode_test_files).and_return(fallback_mode_test_files)
|
13
16
|
|
14
17
|
repository_adapter = double
|
15
18
|
expect(KnapsackPro::RepositoryAdapterInitiator).to receive(:call).and_return(repository_adapter)
|
@@ -20,7 +23,8 @@ describe KnapsackPro::AllocatorBuilder do
|
|
20
23
|
expect(KnapsackPro::Config::Env).to receive(:ci_node_index).and_return(ci_node_index)
|
21
24
|
|
22
25
|
expect(KnapsackPro::Allocator).to receive(:new).with(
|
23
|
-
|
26
|
+
fast_and_slow_test_files_to_run: fast_and_slow_test_files_to_run,
|
27
|
+
fallback_mode_test_files: fallback_mode_test_files,
|
24
28
|
ci_node_total: ci_node_total,
|
25
29
|
ci_node_index: ci_node_index,
|
26
30
|
repository_adapter: repository_adapter,
|
@@ -1,12 +1,14 @@
|
|
1
1
|
describe KnapsackPro::Allocator do
|
2
|
-
let(:
|
2
|
+
let(:fast_and_slow_test_files_to_run) { double }
|
3
|
+
let(:fallback_mode_test_files) { double }
|
3
4
|
let(:ci_node_total) { double }
|
4
5
|
let(:ci_node_index) { double }
|
5
6
|
let(:repository_adapter) { instance_double(KnapsackPro::RepositoryAdapters::EnvAdapter, commit_hash: double, branch: double) }
|
6
7
|
|
7
8
|
let(:allocator) do
|
8
9
|
described_class.new(
|
9
|
-
|
10
|
+
fast_and_slow_test_files_to_run: fast_and_slow_test_files_to_run,
|
11
|
+
fallback_mode_test_files: fallback_mode_test_files,
|
10
12
|
ci_node_total: ci_node_total,
|
11
13
|
ci_node_index: ci_node_index,
|
12
14
|
repository_adapter: repository_adapter
|
@@ -20,7 +22,7 @@ describe KnapsackPro::Allocator do
|
|
20
22
|
|
21
23
|
before do
|
22
24
|
encrypted_test_files = double
|
23
|
-
expect(KnapsackPro::Crypto::Encryptor).to receive(:call).with(
|
25
|
+
expect(KnapsackPro::Crypto::Encryptor).to receive(:call).with(fast_and_slow_test_files_to_run).and_return(encrypted_test_files)
|
24
26
|
|
25
27
|
encrypted_branch = double
|
26
28
|
expect(KnapsackPro::Crypto::BranchEncryptor).to receive(:call).with(repository_adapter.branch).and_return(encrypted_branch)
|
@@ -64,7 +66,7 @@ describe KnapsackPro::Allocator do
|
|
64
66
|
end
|
65
67
|
|
66
68
|
before do
|
67
|
-
expect(KnapsackPro::Crypto::Decryptor).to receive(:call).with(
|
69
|
+
expect(KnapsackPro::Crypto::Decryptor).to receive(:call).with(fast_and_slow_test_files_to_run, response['test_files']).and_call_original
|
68
70
|
end
|
69
71
|
|
70
72
|
it { should eq ['a_spec.rb', 'b_spec.rb'] }
|
@@ -114,7 +116,7 @@ describe KnapsackPro::Allocator do
|
|
114
116
|
context 'when fallback mode started' do
|
115
117
|
before do
|
116
118
|
test_flat_distributor = instance_double(KnapsackPro::TestFlatDistributor)
|
117
|
-
expect(KnapsackPro::TestFlatDistributor).to receive(:new).with(
|
119
|
+
expect(KnapsackPro::TestFlatDistributor).to receive(:new).with(fallback_mode_test_files, ci_node_total).and_return(test_flat_distributor)
|
118
120
|
expect(test_flat_distributor).to receive(:test_files_for_node).with(ci_node_index).and_return([
|
119
121
|
{ 'path' => 'c_spec.rb' },
|
120
122
|
{ 'path' => 'd_spec.rb' },
|
@@ -100,8 +100,22 @@ describe KnapsackPro::BaseAllocatorBuilder do
|
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
103
|
-
describe '#
|
104
|
-
subject { allocator_builder.
|
103
|
+
describe '#fallback_mode_test_files' do
|
104
|
+
subject { allocator_builder.fallback_mode_test_files }
|
105
|
+
|
106
|
+
it do
|
107
|
+
test_file_pattern = double
|
108
|
+
expect(KnapsackPro::TestFilePattern).to receive(:call).with(adapter_class).and_return(test_file_pattern)
|
109
|
+
|
110
|
+
test_files = double
|
111
|
+
expect(KnapsackPro::TestFileFinder).to receive(:call).with(test_file_pattern).and_return(test_files)
|
112
|
+
|
113
|
+
expect(subject).to eq test_files
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe '#fast_and_slow_test_files_to_run' do
|
118
|
+
subject { allocator_builder.fast_and_slow_test_files_to_run }
|
105
119
|
|
106
120
|
context 'when looking for test files on disk by default' do
|
107
121
|
it do
|
@@ -115,10 +129,10 @@ describe KnapsackPro::BaseAllocatorBuilder do
|
|
115
129
|
end
|
116
130
|
end
|
117
131
|
|
118
|
-
context 'when RSpec adapter
|
132
|
+
context 'when RSpec adapter AND rspec split by test examples is enabled' do
|
119
133
|
let(:adapter_class) { KnapsackPro::Adapters::RSpecAdapter }
|
120
|
-
let(:
|
121
|
-
let(:cmd) { 'bundle exec rake knapsack_pro:rspec_test_example_detector' }
|
134
|
+
let(:test_files_to_run) { double }
|
135
|
+
let(:cmd) { 'RACK_ENV=test RAILS_ENV=test bundle exec rake knapsack_pro:rspec_test_example_detector' }
|
122
136
|
|
123
137
|
before do
|
124
138
|
expect(KnapsackPro::Config::Env).to receive(:rspec_split_by_test_examples?).and_return(true)
|
@@ -126,53 +140,91 @@ describe KnapsackPro::BaseAllocatorBuilder do
|
|
126
140
|
test_file_pattern = double
|
127
141
|
expect(KnapsackPro::TestFilePattern).to receive(:call).with(adapter_class).and_return(test_file_pattern)
|
128
142
|
|
129
|
-
expect(KnapsackPro::TestFileFinder).to receive(:call).with(test_file_pattern).and_return(
|
143
|
+
expect(KnapsackPro::TestFileFinder).to receive(:call).with(test_file_pattern).and_return(test_files_to_run)
|
144
|
+
end
|
145
|
+
|
146
|
+
context 'when RSpec version < 3.3.0' do
|
147
|
+
before do
|
148
|
+
stub_const('RSpec::Core::Version::STRING', '3.2.0')
|
149
|
+
end
|
130
150
|
|
131
|
-
|
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://github.com/KnapsackPro/knapsack_pro-ruby#split-test-files-by-test-cases'
|
153
|
+
end
|
132
154
|
end
|
133
155
|
|
134
156
|
context 'when rake task to detect RSpec test examples works' do
|
157
|
+
let(:slow_test_files) { double(size: 5) }
|
135
158
|
let(:cmd_result) { true }
|
136
159
|
let(:test_file_example_paths) { double }
|
137
160
|
let(:logger) { instance_double(Logger) }
|
161
|
+
let(:test_files_with_test_cases) { double }
|
138
162
|
|
139
163
|
before do
|
140
|
-
|
141
|
-
expect(KnapsackPro::TestCaseDetectors::RSpecTestExampleDetector).to receive(:new).and_return(rspec_test_example_detector)
|
142
|
-
expect(rspec_test_example_detector).to receive(:test_file_example_paths).and_return(test_file_example_paths)
|
164
|
+
expect(allocator_builder).to receive(:get_slow_test_files).and_return(slow_test_files)
|
143
165
|
|
144
|
-
expect(KnapsackPro).to receive(:logger).
|
145
|
-
end
|
166
|
+
expect(KnapsackPro).to receive(:logger).and_return(logger)
|
146
167
|
|
147
|
-
|
148
|
-
let(:test_files) { double(size: 1000) }
|
168
|
+
expect(Kernel).to receive(:system).with(cmd).and_return(cmd_result)
|
149
169
|
|
150
|
-
|
151
|
-
|
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)
|
152
173
|
|
153
|
-
|
154
|
-
end
|
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)
|
155
175
|
end
|
156
176
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
it do
|
161
|
-
expect(logger).to receive(:warn).with("Generating RSpec test examples JSON report to prepare your test suite to be split by test examples (by individual 'it's. Thanks to that a single test file can be split across parallel CI nodes). Analyzing 1001 test files.")
|
162
|
-
expect(logger).to receive(:warn).with('You have more than 1000 test files, it may take longer to generate test examples. Please wait...')
|
177
|
+
it do
|
178
|
+
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 'it's. Thanks to that a single slow test file can be split across parallel CI nodes). Analyzing 5 slow test files.")
|
163
179
|
|
164
|
-
|
165
|
-
end
|
180
|
+
expect(subject).to eq test_files_with_test_cases
|
166
181
|
end
|
167
182
|
end
|
168
183
|
|
169
184
|
context 'when rake task to detect RSpec test examples failed' do
|
185
|
+
let(:slow_test_files) { double(size: 5) }
|
170
186
|
let(:cmd_result) { false }
|
171
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
|
193
|
+
|
172
194
|
it do
|
173
|
-
expect { subject }.to raise_error(RuntimeError, 'Could not generate JSON report for RSpec. Rake task failed when running bundle exec rake knapsack_pro:rspec_test_example_detector')
|
195
|
+
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')
|
174
196
|
end
|
175
197
|
end
|
176
198
|
end
|
177
199
|
end
|
200
|
+
|
201
|
+
describe 'private #get_slow_test_files' do
|
202
|
+
subject { allocator_builder.send(:get_slow_test_files) }
|
203
|
+
|
204
|
+
before do
|
205
|
+
expect(KnapsackPro::Config::Env).to receive(:slow_test_file_pattern).and_return(slow_test_file_pattern)
|
206
|
+
end
|
207
|
+
|
208
|
+
context 'when slow test file pattern is present' do
|
209
|
+
let(:slow_test_files) { double(:slow_test_files_based_on_pattern, size: 3) }
|
210
|
+
let(:slow_test_file_pattern) { double }
|
211
|
+
|
212
|
+
before do
|
213
|
+
expect(KnapsackPro::TestFileFinder).to receive(:slow_test_files_by_pattern).with(adapter_class).and_return(slow_test_files)
|
214
|
+
end
|
215
|
+
|
216
|
+
it { expect(subject).to eq slow_test_files }
|
217
|
+
end
|
218
|
+
|
219
|
+
context 'when slow test file pattern is not present' do
|
220
|
+
let(:slow_test_files) { double(:slow_test_files_based_on_api, size: 2) }
|
221
|
+
let(:slow_test_file_pattern) { nil }
|
222
|
+
|
223
|
+
before do
|
224
|
+
expect(KnapsackPro::SlowTestFileFinder).to receive(:call).with(adapter_class).and_return(slow_test_files)
|
225
|
+
end
|
226
|
+
|
227
|
+
it { expect(subject).to eq slow_test_files }
|
228
|
+
end
|
229
|
+
end
|
178
230
|
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
describe KnapsackPro::BuildDistributionFetcher do
|
2
|
+
describe '.call' do
|
3
|
+
subject { described_class.call }
|
4
|
+
|
5
|
+
it do
|
6
|
+
build_distribution_fetcher = instance_double(described_class)
|
7
|
+
expect(described_class).to receive(:new).and_return(build_distribution_fetcher)
|
8
|
+
result = double
|
9
|
+
expect(build_distribution_fetcher).to receive(:call).and_return(result)
|
10
|
+
|
11
|
+
expect(subject).to eq result
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#call' do
|
16
|
+
let(:ci_node_total) { double }
|
17
|
+
let(:ci_node_index) { double }
|
18
|
+
let(:repository_adapter) { instance_double(KnapsackPro::RepositoryAdapters::EnvAdapter, commit_hash: double, branch: double) }
|
19
|
+
|
20
|
+
subject { described_class.new.call }
|
21
|
+
|
22
|
+
before do
|
23
|
+
expect(KnapsackPro::RepositoryAdapterInitiator).to receive(:call).and_return(repository_adapter)
|
24
|
+
|
25
|
+
expect(KnapsackPro::Config::Env).to receive(:ci_node_total).and_return(ci_node_total)
|
26
|
+
expect(KnapsackPro::Config::Env).to receive(:ci_node_index).and_return(ci_node_index)
|
27
|
+
|
28
|
+
action = double
|
29
|
+
expect(KnapsackPro::Client::API::V1::BuildDistributions).to receive(:last).with({
|
30
|
+
commit_hash: repository_adapter.commit_hash,
|
31
|
+
branch: repository_adapter.branch,
|
32
|
+
node_total: ci_node_total,
|
33
|
+
node_index: ci_node_index,
|
34
|
+
}).and_return(action)
|
35
|
+
|
36
|
+
connection = instance_double(KnapsackPro::Client::Connection,
|
37
|
+
call: response,
|
38
|
+
success?: success?,
|
39
|
+
errors?: errors?)
|
40
|
+
expect(KnapsackPro::Client::Connection).to receive(:new).with(action).and_return(connection)
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'when successful request to API' do
|
44
|
+
let(:success?) { true }
|
45
|
+
|
46
|
+
context 'when response has errors' do
|
47
|
+
let(:errors?) { true }
|
48
|
+
let(:response) { 'fake error response' }
|
49
|
+
|
50
|
+
it do
|
51
|
+
expect { subject }.to raise_error(ArgumentError, response)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'when response has no errors' do
|
56
|
+
let(:errors?) { false }
|
57
|
+
let(:response) do
|
58
|
+
{
|
59
|
+
'build_distribution_id' => 'be2b95b1-1b8b-43a3-9d66-cabebbf135b8',
|
60
|
+
'time_execution' => 2.5,
|
61
|
+
'test_files' => [
|
62
|
+
{ 'path' => 'a_spec.rb', 'time_execution' => 1.5 },
|
63
|
+
{ 'path' => 'b_spec.rb', 'time_execution' => 1.0 },
|
64
|
+
]
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
it { expect(subject).to be_a described_class::BuildDistributionEntity }
|
69
|
+
it { expect(subject.time_execution).to eq 2.5 }
|
70
|
+
it do
|
71
|
+
expect(subject.test_files).to eq([
|
72
|
+
{ 'path' => 'a_spec.rb', 'time_execution' => 1.5 },
|
73
|
+
{ 'path' => 'b_spec.rb', 'time_execution' => 1.0 },
|
74
|
+
])
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'when not successful request to API' do
|
80
|
+
let(:success?) { false }
|
81
|
+
let(:errors?) { false }
|
82
|
+
let(:response) { double }
|
83
|
+
|
84
|
+
it { expect(subject).to be_a described_class::BuildDistributionEntity }
|
85
|
+
it { expect(subject.time_execution).to eq 0.0 }
|
86
|
+
it { expect(subject.test_files).to eq([]) }
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|