knapsack_pro 1.20.2 → 1.22.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +45 -0
- data/README.md +43 -18
- 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/runners/queue/rspec_runner.rb +8 -1
- 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/runners/queue/rspec_runner_spec.rb +25 -0
- 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 +27 -10
@@ -4,8 +4,8 @@ module KnapsackPro
|
|
4
4
|
class ServerError < StandardError; end
|
5
5
|
|
6
6
|
TIMEOUT = 15
|
7
|
-
MAX_RETRY = 3
|
8
|
-
REQUEST_RETRY_TIMEBOX =
|
7
|
+
MAX_RETRY = -> { KnapsackPro::Config::Env.fallback_mode_enabled? ? 3 : 6 }
|
8
|
+
REQUEST_RETRY_TIMEBOX = 8
|
9
9
|
|
10
10
|
def initialize(action)
|
11
11
|
@action = action
|
@@ -48,11 +48,7 @@ module KnapsackPro
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def request_hash
|
51
|
-
action
|
52
|
-
.request_hash
|
53
|
-
.merge({
|
54
|
-
test_suite_token: test_suite_token
|
55
|
-
})
|
51
|
+
action.request_hash
|
56
52
|
end
|
57
53
|
|
58
54
|
def request_body
|
@@ -69,6 +65,7 @@ module KnapsackPro
|
|
69
65
|
'Accept' => 'application/json',
|
70
66
|
'KNAPSACK-PRO-CLIENT-NAME' => client_name,
|
71
67
|
'KNAPSACK-PRO-CLIENT-VERSION' => KnapsackPro::VERSION,
|
68
|
+
'KNAPSACK-PRO-TEST-SUITE-TOKEN' => test_suite_token,
|
72
69
|
}
|
73
70
|
end
|
74
71
|
|
@@ -95,19 +92,15 @@ module KnapsackPro
|
|
95
92
|
!seed.nil?
|
96
93
|
end
|
97
94
|
|
98
|
-
def
|
95
|
+
def make_request(&block)
|
99
96
|
retries ||= 0
|
100
|
-
uri = URI.parse(endpoint_url)
|
101
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
102
|
-
http.use_ssl = (uri.scheme == 'https')
|
103
|
-
http.open_timeout = TIMEOUT
|
104
|
-
http.read_timeout = TIMEOUT
|
105
97
|
|
106
|
-
@http_response =
|
98
|
+
@http_response = block.call
|
107
99
|
@response_body = parse_response_body(http_response.body)
|
108
100
|
|
109
101
|
request_uuid = http_response.header['X-Request-Id'] || 'N/A'
|
110
102
|
|
103
|
+
logger.debug("#{action.http_method.to_s.upcase} #{endpoint_url}")
|
111
104
|
logger.debug("API request UUID: #{request_uuid}")
|
112
105
|
logger.debug("Test suite split seed: #{seed}") if has_seed?
|
113
106
|
logger.debug('API response:')
|
@@ -125,15 +118,44 @@ module KnapsackPro
|
|
125
118
|
rescue ServerError, Errno::ECONNREFUSED, Errno::ETIMEDOUT, Errno::EPIPE, EOFError, SocketError, Net::OpenTimeout, Net::ReadTimeout, OpenSSL::SSL::SSLError => e
|
126
119
|
logger.warn(e.inspect)
|
127
120
|
retries += 1
|
128
|
-
if retries < MAX_RETRY
|
121
|
+
if retries < MAX_RETRY.call
|
129
122
|
wait = retries * REQUEST_RETRY_TIMEBOX
|
130
123
|
logger.warn("Wait #{wait}s and retry request to Knapsack Pro API.")
|
131
|
-
|
124
|
+
print_every = 2 # seconds
|
125
|
+
(wait / print_every).ceil.times do |i|
|
126
|
+
logger.warn("Next request in #{wait - i * print_every}s...")
|
127
|
+
Kernel.sleep(print_every)
|
128
|
+
end
|
132
129
|
retry
|
133
130
|
else
|
134
131
|
response_body
|
135
132
|
end
|
136
133
|
end
|
134
|
+
|
135
|
+
def build_http(uri)
|
136
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
137
|
+
http.use_ssl = (uri.scheme == 'https')
|
138
|
+
http.open_timeout = TIMEOUT
|
139
|
+
http.read_timeout = TIMEOUT
|
140
|
+
http
|
141
|
+
end
|
142
|
+
|
143
|
+
def post
|
144
|
+
uri = URI.parse(endpoint_url)
|
145
|
+
http = build_http(uri)
|
146
|
+
make_request do
|
147
|
+
http.post(uri.path, request_body, json_headers)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def get
|
152
|
+
uri = URI.parse(endpoint_url)
|
153
|
+
uri.query = URI.encode_www_form(request_hash)
|
154
|
+
http = build_http(uri)
|
155
|
+
make_request do
|
156
|
+
http.get(uri, json_headers)
|
157
|
+
end
|
158
|
+
end
|
137
159
|
end
|
138
160
|
end
|
139
161
|
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
module KnapsackPro
|
2
2
|
class QueueAllocator
|
3
3
|
def initialize(args)
|
4
|
-
@
|
4
|
+
@fast_and_slow_test_files_to_run = args.fetch(:fast_and_slow_test_files_to_run)
|
5
|
+
@fallback_mode_test_files = args.fetch(:fallback_mode_test_files)
|
5
6
|
@ci_node_total = args.fetch(:ci_node_total)
|
6
7
|
@ci_node_index = args.fetch(:ci_node_index)
|
7
8
|
@ci_node_build_id = args.fetch(:ci_node_build_id)
|
@@ -36,14 +37,15 @@ module KnapsackPro
|
|
36
37
|
|
37
38
|
private
|
38
39
|
|
39
|
-
attr_reader :
|
40
|
+
attr_reader :fast_and_slow_test_files_to_run,
|
41
|
+
:fallback_mode_test_files,
|
40
42
|
:ci_node_total,
|
41
43
|
:ci_node_index,
|
42
44
|
:ci_node_build_id,
|
43
45
|
:repository_adapter
|
44
46
|
|
45
47
|
def encrypted_test_files
|
46
|
-
KnapsackPro::Crypto::Encryptor.call(
|
48
|
+
KnapsackPro::Crypto::Encryptor.call(fast_and_slow_test_files_to_run)
|
47
49
|
end
|
48
50
|
|
49
51
|
def encrypted_branch
|
@@ -63,12 +65,12 @@ module KnapsackPro
|
|
63
65
|
end
|
64
66
|
|
65
67
|
def prepare_test_files(response)
|
66
|
-
decrypted_test_files = KnapsackPro::Crypto::Decryptor.call(
|
68
|
+
decrypted_test_files = KnapsackPro::Crypto::Decryptor.call(fast_and_slow_test_files_to_run, response['test_files'])
|
67
69
|
KnapsackPro::TestFilePresenter.paths(decrypted_test_files)
|
68
70
|
end
|
69
71
|
|
70
72
|
def fallback_test_files(executed_test_files)
|
71
|
-
test_flat_distributor = KnapsackPro::TestFlatDistributor.new(
|
73
|
+
test_flat_distributor = KnapsackPro::TestFlatDistributor.new(fallback_mode_test_files, ci_node_total)
|
72
74
|
test_files_for_node_index = test_flat_distributor.test_files_for_node(ci_node_index)
|
73
75
|
KnapsackPro::TestFilePresenter.paths(test_files_for_node_index) - executed_test_files
|
74
76
|
end
|
@@ -2,7 +2,8 @@ module KnapsackPro
|
|
2
2
|
class QueueAllocatorBuilder < BaseAllocatorBuilder
|
3
3
|
def allocator
|
4
4
|
KnapsackPro::QueueAllocator.new(
|
5
|
-
|
5
|
+
fast_and_slow_test_files_to_run: fast_and_slow_test_files_to_run,
|
6
|
+
fallback_mode_test_files: fallback_mode_test_files,
|
6
7
|
ci_node_total: env.ci_node_total,
|
7
8
|
ci_node_index: env.ci_node_index,
|
8
9
|
ci_node_build_id: env.ci_node_build_id,
|
@@ -16,7 +16,7 @@ module KnapsackPro
|
|
16
16
|
cli_args = (args || '').split
|
17
17
|
# if user didn't provide the format then use explicitly default progress formatter
|
18
18
|
# in order to avoid KnapsackPro::Formatters::RSpecQueueSummaryFormatter being the only default formatter
|
19
|
-
if !cli_args.
|
19
|
+
if !cli_args.any? { |arg| arg.start_with?('-f') || arg.start_with?('--format')}
|
20
20
|
cli_args += ['--format', 'progress']
|
21
21
|
end
|
22
22
|
cli_args += [
|
@@ -134,6 +134,13 @@ module KnapsackPro
|
|
134
134
|
RSpec.world.example_groups.clear
|
135
135
|
RSpec.configuration.start_time = ::RSpec::Core::Time.now
|
136
136
|
|
137
|
+
if KnapsackPro::Config::Env.rspec_split_by_test_examples?
|
138
|
+
# Reset example group counts to ensure scoped example ids in metadata
|
139
|
+
# have correct index (not increased by each subsequent run).
|
140
|
+
# Solves this problem: https://github.com/rspec/rspec-core/issues/2721
|
141
|
+
RSpec.world.instance_variable_set(:@example_group_counts_by_spec_file, Hash.new(0))
|
142
|
+
end
|
143
|
+
|
137
144
|
# skip reset filters for old RSpec versions
|
138
145
|
if RSpec.configuration.respond_to?(:reset_filters)
|
139
146
|
RSpec.configuration.reset_filters
|
@@ -16,8 +16,11 @@ module KnapsackPro
|
|
16
16
|
end
|
17
17
|
|
18
18
|
RSpec::Core::RakeTask.new(task_name) do |t|
|
19
|
-
|
20
|
-
|
19
|
+
# we cannot pass runner.test_file_paths array to t.pattern
|
20
|
+
# because pattern does not accept test example path like spec/a_spec.rb[1:2]
|
21
|
+
# instead we pass test files and test example paths to t.rspec_opts
|
22
|
+
t.pattern = []
|
23
|
+
t.rspec_opts = "#{args} --default-path #{runner.test_dir} #{runner.stringify_test_file_paths}"
|
21
24
|
end
|
22
25
|
Rake::Task[task_name].invoke
|
23
26
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module KnapsackPro
|
2
|
+
class SlowTestFileDeterminer
|
3
|
+
TIME_THRESHOLD_PER_CI_NODE = 0.7 # 70%
|
4
|
+
REPORT_DIR = 'tmp/knapsack_pro/slow_test_file_determiner'
|
5
|
+
|
6
|
+
# test_files: { 'path' => 'a_spec.rb', 'time_execution' => 0.0 }
|
7
|
+
# time_execution: of build distribution (total time of CI build run)
|
8
|
+
def self.call(test_files, time_execution)
|
9
|
+
time_threshold = (time_execution / KnapsackPro::Config::Env.ci_node_total) * TIME_THRESHOLD_PER_CI_NODE
|
10
|
+
|
11
|
+
test_files.select do |test_file|
|
12
|
+
test_file.fetch('time_execution') >= time_threshold
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.save_to_json_report(test_files)
|
17
|
+
FileUtils.mkdir_p(REPORT_DIR)
|
18
|
+
File.write(report_path, test_files.to_json)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.read_from_json_report
|
22
|
+
raise 'Report with slow test files was not generated yet. If you have enabled split by test cases https://github.com/KnapsackPro/knapsack_pro-ruby#split-test-files-by-test-cases and you see this error it means that your tests accidentally cleaned up tmp/knapsack_pro directory. Please do not remove this directory during tests runtime!' unless File.exists?(report_path)
|
23
|
+
slow_test_files_json_report = File.read(report_path)
|
24
|
+
JSON.parse(slow_test_files_json_report)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def self.report_path
|
30
|
+
"#{REPORT_DIR}/slow_test_files_node_#{KnapsackPro::Config::Env.ci_node_index}.json"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module KnapsackPro
|
2
|
+
class SlowTestFileFinder
|
3
|
+
# Get recorded test files from API.
|
4
|
+
# Find slow tests among them that are still present on the disk.
|
5
|
+
# Save slow test files in json file on the disk.
|
6
|
+
# Returns slow test files.
|
7
|
+
def self.call(adapter_class)
|
8
|
+
if KnapsackPro::Config::Env.test_files_encrypted?
|
9
|
+
raise 'Split by test cases is not possible when you have enabled test file names encryption ( https://github.com/KnapsackPro/knapsack_pro-ruby#test-file-names-encryption ). You need to disable encryption with KNAPSACK_PRO_TEST_FILES_ENCRYPTED=false in order to use split by test cases https://github.com/KnapsackPro/knapsack_pro-ruby#split-test-files-by-test-cases'
|
10
|
+
end
|
11
|
+
|
12
|
+
# get list of recorded test files for last CI Build
|
13
|
+
build_distribution_entity = KnapsackPro::BuildDistributionFetcher.call
|
14
|
+
test_files_from_api = build_distribution_entity.test_files
|
15
|
+
|
16
|
+
merged_test_files_from_api = KnapsackPro::TestCaseMergers::BaseMerger.call(adapter_class, test_files_from_api)
|
17
|
+
|
18
|
+
test_files_existing_on_disk = KnapsackPro::TestFileFinder.select_test_files_that_can_be_run(adapter_class, merged_test_files_from_api)
|
19
|
+
|
20
|
+
slow_test_files = KnapsackPro::SlowTestFileDeterminer.call(test_files_existing_on_disk, build_distribution_entity.time_execution)
|
21
|
+
|
22
|
+
KnapsackPro::SlowTestFileDeterminer.save_to_json_report(slow_test_files)
|
23
|
+
|
24
|
+
slow_test_files
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -2,7 +2,6 @@ module KnapsackPro
|
|
2
2
|
module TestCaseDetectors
|
3
3
|
class RSpecTestExampleDetector
|
4
4
|
REPORT_DIR = 'tmp/knapsack_pro/test_case_detectors/rspec'
|
5
|
-
REPORT_PATH = "#{REPORT_DIR}/rspec_dry_run_json_report.json"
|
6
5
|
|
7
6
|
def generate_json_report
|
8
7
|
require 'rspec/core'
|
@@ -18,13 +17,19 @@ module KnapsackPro
|
|
18
17
|
ensure_report_dir_exists
|
19
18
|
remove_old_json_report
|
20
19
|
|
21
|
-
|
20
|
+
test_file_entities = slow_test_files
|
21
|
+
|
22
|
+
if test_file_entities.empty?
|
23
|
+
no_examples_json = { examples: [] }.to_json
|
24
|
+
File.write(report_path, no_examples_json)
|
25
|
+
return
|
26
|
+
end
|
22
27
|
|
23
28
|
cli_args = cli_format + [
|
24
29
|
'--dry-run',
|
25
|
-
'--out',
|
30
|
+
'--out', report_path,
|
26
31
|
'--default-path', test_dir,
|
27
|
-
] +
|
32
|
+
] + KnapsackPro::TestFilePresenter.paths(test_file_entities)
|
28
33
|
options = RSpec::Core::ConfigurationOptions.new(cli_args)
|
29
34
|
exit_code = RSpec::Core::Runner.new(options).run($stderr, $stdout)
|
30
35
|
if exit_code != 0
|
@@ -33,9 +38,9 @@ module KnapsackPro
|
|
33
38
|
end
|
34
39
|
|
35
40
|
def test_file_example_paths
|
36
|
-
raise "No report found at #{
|
41
|
+
raise "No report found at #{report_path}" unless File.exists?(report_path)
|
37
42
|
|
38
|
-
json_report = File.read(
|
43
|
+
json_report = File.read(report_path)
|
39
44
|
hash_report = JSON.parse(json_report)
|
40
45
|
hash_report
|
41
46
|
.fetch('examples')
|
@@ -43,8 +48,22 @@ module KnapsackPro
|
|
43
48
|
.map { |path_with_example_id| test_file_hash_for(path_with_example_id) }
|
44
49
|
end
|
45
50
|
|
51
|
+
def slow_test_files
|
52
|
+
if KnapsackPro::Config::Env.slow_test_file_pattern
|
53
|
+
KnapsackPro::TestFileFinder.slow_test_files_by_pattern(adapter_class)
|
54
|
+
else
|
55
|
+
# read slow test files from JSON file on disk that was generated
|
56
|
+
# by lib/knapsack_pro/base_allocator_builder.rb
|
57
|
+
KnapsackPro::SlowTestFileDeterminer.read_from_json_report
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
46
61
|
private
|
47
62
|
|
63
|
+
def report_path
|
64
|
+
"#{REPORT_DIR}/rspec_dry_run_json_report_node_#{KnapsackPro::Config::Env.ci_node_index}.json"
|
65
|
+
end
|
66
|
+
|
48
67
|
def adapter_class
|
49
68
|
KnapsackPro::Adapters::RSpecAdapter
|
50
69
|
end
|
@@ -62,7 +81,7 @@ module KnapsackPro
|
|
62
81
|
end
|
63
82
|
|
64
83
|
def remove_old_json_report
|
65
|
-
File.delete(
|
84
|
+
File.delete(report_path) if File.exists?(report_path)
|
66
85
|
end
|
67
86
|
|
68
87
|
def test_file_hash_for(test_file_path)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module KnapsackPro
|
2
|
+
module TestCaseMergers
|
3
|
+
class BaseMerger
|
4
|
+
# values must be string to avoid circular dependency problem during loading files
|
5
|
+
ADAPTER_TO_MERGER_MAP = {
|
6
|
+
KnapsackPro::Adapters::RSpecAdapter => 'KnapsackPro::TestCaseMergers::RSpecMerger',
|
7
|
+
}
|
8
|
+
|
9
|
+
def self.call(adapter_class, test_files)
|
10
|
+
merger_class =
|
11
|
+
ADAPTER_TO_MERGER_MAP[adapter_class] ||
|
12
|
+
raise("Test case merger does not exist for adapter_class: #{adapter_class}")
|
13
|
+
Kernel.const_get(merger_class).new(test_files).call
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(test_files)
|
17
|
+
@test_files = test_files
|
18
|
+
end
|
19
|
+
|
20
|
+
def call
|
21
|
+
raise NotImplementedError
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
attr_reader :test_files
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module KnapsackPro
|
2
|
+
module TestCaseMergers
|
3
|
+
class RSpecMerger < BaseMerger
|
4
|
+
def call
|
5
|
+
merged_test_files_hash = {}
|
6
|
+
test_files.each do |test_file|
|
7
|
+
test_file_path = extract_test_file_path(test_file.fetch('path'))
|
8
|
+
|
9
|
+
# must be float (default type for time execution from API)
|
10
|
+
merged_test_files_hash[test_file_path] ||= 0.0
|
11
|
+
merged_test_files_hash[test_file_path] += test_file.fetch('time_execution')
|
12
|
+
end
|
13
|
+
|
14
|
+
merged_test_files = []
|
15
|
+
merged_test_files_hash.each do |path, time_execution|
|
16
|
+
merged_test_files << {
|
17
|
+
'path' => path,
|
18
|
+
'time_execution' => time_execution
|
19
|
+
}
|
20
|
+
end
|
21
|
+
merged_test_files
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
# path - can be:
|
27
|
+
# test file path: spec/a_spec.rb
|
28
|
+
# or test example path: spec/a_spec.rb[1:1]
|
29
|
+
def extract_test_file_path(path)
|
30
|
+
path.gsub(/\.rb\[.+\]$/, '.rb')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,11 +1,49 @@
|
|
1
1
|
module KnapsackPro
|
2
2
|
class TestFileFinder
|
3
|
-
def self.call(test_file_pattern)
|
4
|
-
new(test_file_pattern).call
|
3
|
+
def self.call(test_file_pattern, test_file_list_enabled: true)
|
4
|
+
new(test_file_pattern, test_file_list_enabled).call
|
5
5
|
end
|
6
6
|
|
7
|
-
|
7
|
+
# finds slow test files on disk based on ENV patterns
|
8
|
+
# returns example: [{ 'path' => 'a_spec.rb' }]
|
9
|
+
def self.slow_test_files_by_pattern(adapter_class)
|
10
|
+
raise 'KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN is not defined' unless KnapsackPro::Config::Env.slow_test_file_pattern
|
11
|
+
|
12
|
+
test_file_pattern = KnapsackPro::TestFilePattern.call(adapter_class)
|
13
|
+
test_file_entities = call(test_file_pattern)
|
14
|
+
|
15
|
+
slow_test_file_entities = call(KnapsackPro::Config::Env.slow_test_file_pattern, test_file_list_enabled: false)
|
16
|
+
|
17
|
+
# slow test files (KNAPSACK_PRO_SLOW_TEST_FILE_PATTERN)
|
18
|
+
# should be subset of test file pattern (KNAPSACK_PRO_TEST_FILE_PATTERN)
|
19
|
+
slow_test_file_entities & test_file_entities
|
20
|
+
end
|
21
|
+
|
22
|
+
# Args:
|
23
|
+
# test_file_entities_to_run - it can be list of slow test files that you want to run
|
24
|
+
# Return:
|
25
|
+
# subset of test_file_entities_to_run that are present on disk and it is subset of tests matching pattern KNAPSACK_PRO_TEST_FILE_PATTERN
|
26
|
+
# Thanks to that we can select only slow test files that are within list of test file pattern we want to run tests for
|
27
|
+
def self.select_test_files_that_can_be_run(adapter_class, test_file_entities_to_run)
|
28
|
+
test_file_pattern = KnapsackPro::TestFilePattern.call(adapter_class)
|
29
|
+
test_file_entities = call(test_file_pattern)
|
30
|
+
|
31
|
+
test_file_paths_existing_on_disk = KnapsackPro::TestFilePresenter.paths(test_file_entities)
|
32
|
+
|
33
|
+
selected_test_files = []
|
34
|
+
|
35
|
+
test_file_entities_to_run.each do |test_file_entity|
|
36
|
+
if test_file_paths_existing_on_disk.include?(test_file_entity.fetch('path'))
|
37
|
+
selected_test_files << test_file_entity
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
selected_test_files
|
42
|
+
end
|
43
|
+
|
44
|
+
def initialize(test_file_pattern, test_file_list_enabled)
|
8
45
|
@test_file_pattern = test_file_pattern
|
46
|
+
@test_file_list_enabled = test_file_list_enabled
|
9
47
|
end
|
10
48
|
|
11
49
|
def call
|
@@ -18,10 +56,10 @@ module KnapsackPro
|
|
18
56
|
|
19
57
|
private
|
20
58
|
|
21
|
-
attr_reader :test_file_pattern
|
59
|
+
attr_reader :test_file_pattern, :test_file_list_enabled
|
22
60
|
|
23
61
|
def test_files
|
24
|
-
if KnapsackPro::Config::Env.test_file_list
|
62
|
+
if test_file_list_enabled && KnapsackPro::Config::Env.test_file_list
|
25
63
|
return KnapsackPro::Config::Env.test_file_list.split(',').map(&:strip)
|
26
64
|
end
|
27
65
|
|