fastlane-plugin-test_center 3.7.0.parallelizing.alpha.4 → 3.7.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.
Files changed (23) hide show
  1. checksums.yaml +4 -4
  2. data/lib/fastlane/plugin/test_center.rb +1 -1
  3. data/lib/fastlane/plugin/test_center/actions/collate_test_result_bundles.rb +1 -1
  4. data/lib/fastlane/plugin/test_center/actions/multi_scan.rb +34 -89
  5. data/lib/fastlane/plugin/test_center/helper/correcting_scan_helper.rb +315 -0
  6. data/lib/fastlane/plugin/test_center/helper/reportname_helper.rb +6 -15
  7. data/lib/fastlane/plugin/test_center/helper/test_collector.rb +11 -48
  8. data/lib/fastlane/plugin/test_center/version.rb +1 -1
  9. metadata +11 -24
  10. data/lib/fastlane/plugin/test_center/actions/restart_core_simulator_service.rb +0 -38
  11. data/lib/fastlane/plugin/test_center/helper/multi_scan_manager.rb +0 -5
  12. data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/device_manager.rb +0 -30
  13. data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/interstitial.rb +0 -143
  14. data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/parallel_test_batch_worker.rb +0 -27
  15. data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/report_collator.rb +0 -115
  16. data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/retrying_scan.rb +0 -74
  17. data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/retrying_scan_helper.rb +0 -255
  18. data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/runner.rb +0 -356
  19. data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/simulator_helper.rb +0 -49
  20. data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/simulator_manager.rb +0 -317
  21. data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/test_batch_worker.rb +0 -20
  22. data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/test_batch_worker_pool.rb +0 -129
  23. data/lib/fastlane/plugin/test_center/helper/xctestrun_info.rb +0 -42
@@ -1,27 +0,0 @@
1
- module TestCenter
2
- module Helper
3
- module MultiScanManager
4
- class ParallelTestBatchWorker < TestBatchWorker
5
- attr_reader :pid
6
-
7
- def state=(new_state)
8
- super(new_state)
9
- @pid = nil unless new_state == :working
10
- end
11
-
12
- def run(run_options)
13
- self.state = :working
14
- @pid = Process.fork do
15
- begin
16
- super(run_options)
17
- ensure
18
- exit!
19
- end
20
- end
21
- end
22
- end
23
- end
24
- end
25
- end
26
-
27
-
@@ -1,115 +0,0 @@
1
- module TestCenter
2
- module Helper
3
- module MultiScanManager
4
- class ReportCollator
5
- CollateJunitReportsAction = Fastlane::Actions::CollateJunitReportsAction
6
- CollateHtmlReportsAction = Fastlane::Actions::CollateHtmlReportsAction
7
- CollateJsonReportsAction = Fastlane::Actions::CollateJsonReportsAction
8
- CollateTestResultBundlesAction = Fastlane::Actions::CollateTestResultBundlesAction
9
-
10
- def initialize(params)
11
- @source_reports_directory_glob = params[:source_reports_directory_glob]
12
- @output_directory = params[:output_directory]
13
- @reportnamer = params[:reportnamer]
14
- @scheme = params[:scheme]
15
- @result_bundle = params[:result_bundle]
16
- @suffix = params[:suffix] || ''
17
- end
18
-
19
- def collate
20
- collate_junit_reports
21
- collate_html_reports
22
- collate_json_reports
23
- collate_test_result_bundles
24
- end
25
-
26
- def sort_globbed_files(glob)
27
- files = Dir.glob(glob).map do |relative_filepath|
28
- File.absolute_path(relative_filepath)
29
- end
30
- files.sort! { |f1, f2| File.mtime(f1) <=> File.mtime(f2) }
31
- end
32
-
33
- def delete_globbed_intermediatefiles(glob)
34
- retried_reportfiles = Dir.glob(glob)
35
- FileUtils.rm_f(retried_reportfiles)
36
- end
37
-
38
- def create_config(klass, options)
39
- FastlaneCore::Configuration.create(klass.available_options, options)
40
- end
41
-
42
- def collate_junit_reports
43
- glob = "#{@source_reports_directory_glob}/#{@reportnamer.junit_fileglob}"
44
- report_files = sort_globbed_files(glob)
45
- if report_files.size > 1
46
- collated_file = File.absolute_path(File.join(@output_directory, @reportnamer.junit_reportname(@suffix)))
47
- config = create_config(
48
- CollateJunitReportsAction,
49
- {
50
- reports: report_files,
51
- collated_report: collated_file
52
- }
53
- )
54
- CollateJunitReportsAction.run(config)
55
- FileUtils.rm_rf(report_files - [collated_file])
56
- end
57
- end
58
-
59
- def collate_html_reports
60
- return unless @reportnamer.includes_html?
61
-
62
- report_files = sort_globbed_files("#{@source_reports_directory_glob}/#{@reportnamer.html_fileglob}")
63
- if report_files.size > 1
64
- collated_file = File.absolute_path(File.join(@output_directory, @reportnamer.html_reportname(@suffix)))
65
- config = create_config(
66
- CollateJunitReportsAction,
67
- {
68
- reports: report_files,
69
- collated_report: collated_file
70
- }
71
- )
72
- CollateHtmlReportsAction.run(config)
73
- FileUtils.rm_rf(report_files - [collated_file])
74
- end
75
- end
76
-
77
- def collate_json_reports
78
- return unless @reportnamer.includes_json?
79
-
80
- report_files = sort_globbed_files("#{@source_reports_directory_glob}/#{@reportnamer.json_fileglob}")
81
- if report_files.size > 1
82
- collated_file = File.absolute_path(File.join(@output_directory, @reportnamer.json_reportname(@suffix)))
83
- config = create_config(
84
- CollateJsonReportsAction,
85
- {
86
- reports: report_files,
87
- collated_report: collated_file
88
- }
89
- )
90
- CollateJsonReportsAction.run(config)
91
- FileUtils.rm_rf(report_files - [collated_file])
92
- end
93
- end
94
-
95
- def collate_test_result_bundles
96
- return unless @result_bundle
97
-
98
- test_result_bundlepaths = sort_globbed_files("#{@source_reports_directory_glob}/#{@scheme}*.test_result")
99
- if test_result_bundlepaths.size > 1
100
- collated_test_result_bundlepath = File.absolute_path("#{File.join(@output_directory, @scheme)}.test_result")
101
- config = create_config(
102
- CollateTestResultBundlesAction,
103
- {
104
- bundles: test_result_bundlepaths,
105
- collated_bundle: collated_test_result_bundlepath
106
- }
107
- )
108
- CollateTestResultBundlesAction.run(config)
109
- FileUtils.rm_rf(test_result_bundlepaths - [collated_test_result_bundlepath])
110
- end
111
- end
112
- end
113
- end
114
- end
115
- end
@@ -1,74 +0,0 @@
1
- module TestCenter
2
- module Helper
3
- module MultiScanManager
4
-
5
- class RetryingScan
6
- def initialize(options = {})
7
- @options = options
8
- @retrying_scan_helper = RetryingScanHelper.new(options)
9
- end
10
-
11
- def scan_config
12
- Scan.config
13
- end
14
-
15
- def scan_cache
16
- Scan.cache
17
- end
18
-
19
- def prepare_scan_config_for_destination
20
- # this allows multi_scan's `destination` option to be picked up by `scan`
21
- scan_config._values.delete(:device)
22
- scan_config._values.delete(:devices)
23
- scan_cache.clear
24
- end
25
-
26
- def update_scan_options
27
- valid_scan_keys = Fastlane::Actions::ScanAction.available_options.map(&:key)
28
- scan_options = @options.select { |k,v| valid_scan_keys.include?(k) }
29
- .merge(@retrying_scan_helper.scan_options)
30
-
31
- prepare_scan_config_for_destination
32
- scan_options.each do |k,v|
33
- scan_config.set(k,v) unless v.nil?
34
- end
35
- end
36
-
37
- def self.run(options)
38
- RetryingScan.new(options).run
39
- end
40
-
41
- def run
42
- try_count = @options[:try_count] || 1
43
- begin
44
- # TODO move delete_xcresults to `before_testrun`
45
- @retrying_scan_helper.before_testrun
46
- update_scan_options
47
-
48
- values = scan_config.values(ask: false)
49
- values[:xcode_path] = File.expand_path("../..", FastlaneCore::Helper.xcode_path)
50
- FastlaneCore::PrintTable.print_values(
51
- config: values,
52
- hide_keys: [:destination, :slack_url],
53
- title: "Summary for scan #{Fastlane::VERSION}"
54
- ) unless FastlaneCore::Helper.test?
55
-
56
- Scan::Runner.new.run
57
- @retrying_scan_helper.after_testrun
58
- true
59
- rescue FastlaneCore::Interface::FastlaneTestFailure => e
60
- FastlaneCore::UI.message("retrying_scan after test failure")
61
- @retrying_scan_helper.after_testrun(e)
62
- retry if @retrying_scan_helper.testrun_count < try_count
63
- false
64
- rescue FastlaneCore::Interface::FastlaneBuildFailure => e
65
- FastlaneCore::UI.message("retrying_scan after build failure")
66
- @retrying_scan_helper.after_testrun(e)
67
- retry if @retrying_scan_helper.testrun_count < try_count
68
- false
69
- end
70
- end
71
- end
72
- end
73
- end
74
- end
@@ -1,255 +0,0 @@
1
- module TestCenter
2
- module Helper
3
- module MultiScanManager
4
- require_relative 'device_manager'
5
-
6
- class RetryingScanHelper
7
-
8
- attr_reader :testrun_count
9
-
10
- def initialize(options)
11
- raise ArgumentError, 'Do not use the :device or :devices option. Instead use the :destination option.' if (options.key?(:device) or options.key?(:devices))
12
-
13
- @options = options
14
- @testrun_count = 0
15
- @xcpretty_json_file_output = ENV['XCPRETTY_JSON_FILE_OUTPUT']
16
- @reportnamer = ReportNameHelper.new(
17
- @options[:output_types],
18
- @options[:output_files],
19
- @options[:custom_report_file_name]
20
- )
21
- end
22
-
23
- def before_testrun
24
- remove_preexisting_test_result_bundles
25
- delete_xcresults # has to be performed _after_ moving a *.test_result
26
-
27
- set_json_env
28
- print_starting_scan_message
29
- end
30
-
31
- def delete_xcresults
32
- derived_data_path = File.expand_path(@options[:derived_data_path] || Scan.config[:derived_data_path])
33
- xcresults = Dir.glob("#{derived_data_path}/Logs/Test/*.xcresult")
34
- FastlaneCore::UI.message("Deleting xcresults: #{xcresults}")
35
- FileUtils.rm_rf(xcresults)
36
- end
37
-
38
- def output_directory
39
- absolute_output_directory = File.absolute_path(@options[:output_directory])
40
- if @options[:batch]
41
- testable = @options.fetch(:only_testing, ['']).first.split('/').first || ''
42
- absolute_output_directory = File.join(absolute_output_directory, "#{testable}-batch-#{@options[:batch]}")
43
- end
44
- absolute_output_directory
45
- end
46
-
47
- def print_starting_scan_message
48
- scan_message = "Starting scan ##{@testrun_count + 1} with #{@options.fetch(:only_testing, []).size} tests"
49
- scan_message << " for batch ##{@options[:batch]}" unless @options[:batch].nil?
50
- FastlaneCore::UI.message("#{scan_message}.")
51
- end
52
-
53
- def set_json_env
54
- return unless @reportnamer.includes_json?
55
-
56
- ENV['XCPRETTY_JSON_FILE_OUTPUT'] = File.join(
57
- output_directory,
58
- @reportnamer.json_last_reportname
59
- )
60
- end
61
-
62
- def reset_json_env
63
- return unless @reportnamer.includes_json?
64
-
65
- ENV['XCPRETTY_JSON_FILE_OUTPUT'] = @xcpretty_json_file_output
66
- end
67
-
68
- def remove_preexisting_test_result_bundles
69
- return unless @options[:result_bundle]
70
-
71
- glob_pattern = "#{output_directory}/*.test_result"
72
- preexisting_test_result_bundles = Dir.glob(glob_pattern)
73
- FileUtils.rm_rf(preexisting_test_result_bundles)
74
- end
75
-
76
- def scan_options
77
- valid_scan_keys = Fastlane::Actions::ScanAction.available_options.map(&:key)
78
- @options.select { |k,v| valid_scan_keys.include?(k) }
79
- .merge(@reportnamer.scan_options)
80
- .merge(output_directory: output_directory)
81
- end
82
-
83
- # after_testrun methods
84
-
85
- def after_testrun(exception = nil)
86
- @testrun_count = @testrun_count + 1
87
- if exception.kind_of?(FastlaneCore::Interface::FastlaneTestFailure)
88
- handle_test_failure
89
- elsif exception.kind_of?(FastlaneCore::Interface::FastlaneBuildFailure)
90
- handle_build_failure(exception)
91
- else
92
- handle_success
93
- end
94
- collate_reports
95
- end
96
-
97
- def handle_success
98
- send_callback_testrun_info
99
- move_test_result_bundle_for_next_run
100
- reset_json_env
101
- end
102
-
103
- def collate_reports
104
-
105
- report_collator_options = {
106
- source_reports_directory_glob: output_directory,
107
- output_directory: output_directory,
108
- reportnamer: @reportnamer,
109
- scheme: @options[:scheme],
110
- result_bundle: @options[:result_bundle]
111
- }
112
- TestCenter::Helper::MultiScanManager::ReportCollator.new(report_collator_options).collate
113
- end
114
-
115
- def handle_test_failure
116
- send_callback_testrun_info
117
- reset_simulators
118
- move_test_result_bundle_for_next_run
119
- update_scan_options
120
- @reportnamer.increment
121
- end
122
-
123
- def send_callback_testrun_info(additional_info = {})
124
- return unless @options[:testrun_completed_block]
125
-
126
- report_filepath = nil
127
- junit_results = {}
128
- unless additional_info.key?(:test_operation_failure)
129
- report_filepath = File.join(output_directory, @reportnamer.junit_last_reportname)
130
-
131
- config = FastlaneCore::Configuration.create(
132
- Fastlane::Actions::TestsFromJunitAction.available_options,
133
- {
134
- junit: File.absolute_path(report_filepath)
135
- }
136
- )
137
- junit_results = Fastlane::Actions::TestsFromJunitAction.run(config)
138
- end
139
-
140
- info = {
141
- failed: junit_results[:failed],
142
- passing: junit_results[:passing],
143
- batch: @options[:batch] || 1,
144
- try_count: @testrun_count,
145
- report_filepath: report_filepath
146
- }.merge(additional_info)
147
-
148
- if @reportnamer.includes_html?
149
- html_report_filepath = File.join(output_directory, @reportnamer.html_last_reportname)
150
- info[:html_report_filepath] = html_report_filepath
151
- end
152
- if @reportnamer.includes_json?
153
- json_report_filepath = File.join(output_directory, @reportnamer.json_last_reportname)
154
- info[:json_report_filepath] = json_report_filepath
155
- end
156
- if @options[:result_bundle]
157
- test_result_suffix = '.test_result'
158
- test_result_suffix.prepend("-#{@reportnamer.report_count}") unless @reportnamer.report_count.zero?
159
- test_result_bundlepath = File.join(output_directory, @options[:scheme]) + test_result_suffix
160
- info[:test_result_bundlepath] = test_result_bundlepath
161
- end
162
- @options[:testrun_completed_block].call(info)
163
- end
164
-
165
- def update_scan_options
166
- update_only_testing
167
- turn_off_code_coverage
168
- end
169
-
170
- def turn_off_code_coverage
171
- # Turn off code coverage as code coverage reports are not merged and
172
- # the first, more valuable, report will be overwritten
173
- @options.delete(:code_coverage)
174
- end
175
-
176
- def update_only_testing
177
- report_filepath = File.join(output_directory, @reportnamer.junit_last_reportname)
178
- config = FastlaneCore::Configuration.create(
179
- Fastlane::Actions::TestsFromJunitAction.available_options,
180
- {
181
- junit: File.absolute_path(report_filepath)
182
- }
183
- )
184
- @options[:only_testing] = Fastlane::Actions::TestsFromJunitAction.run(config)[:failed]
185
- if @options[:invocation_based_tests]
186
- @options[:only_testing] = @options[:only_testing].map(&:strip_testcase).uniq
187
- end
188
- end
189
-
190
- def reset_simulators
191
- return unless @options[:reset_simulators]
192
-
193
- @options[:simulators].each(&:reset)
194
- end
195
-
196
- def handle_build_failure(exception)
197
- test_operation_failure = ''
198
-
199
- test_session_last_messages = last_lines_of_test_session_log
200
- test_operation_failure_match = /Test operation failure: (?<test_operation_failure>.*)$/ =~ test_session_last_messages
201
- if test_operation_failure_match.nil?
202
- test_operation_failure = 'Unknown test operation failure'
203
- end
204
-
205
- case test_operation_failure
206
- when /Test runner exited before starting test execution/
207
- FastlaneCore::UI.error(test_operation_failure)
208
- when /Lost connection to testmanagerd/
209
- FastlaneCore::UI.error(test_operation_failure)
210
- FastlaneCore::UI.important("com.apple.CoreSimulator.CoreSimulatorService may have become corrupt, consider quitting it")
211
- if @options[:quit_core_simulator_service]
212
- Fastlane::Actions::RestartCoreSimulatorServiceAction.run
213
- end
214
- else
215
- FastlaneCore::UI.error(test_operation_failure)
216
- send_callback_testrun_info(test_operation_failure: test_operation_failure)
217
- raise exception
218
- end
219
- if @options[:reset_simulators]
220
- @options[:simulators].each do |simulator|
221
- simulator.reset
222
- end
223
- end
224
- send_callback_testrun_info(test_operation_failure: test_operation_failure)
225
- end
226
-
227
- def last_lines_of_test_session_log
228
- derived_data_path = File.expand_path(@options[:derived_data_path])
229
- test_session_logs = Dir.glob("#{derived_data_path}/Logs/Test/*.xcresult/*_Test/Diagnostics/**/Session-*.log")
230
- test_session_logs.sort! { |logfile1, logfile2| File.mtime(logfile1) <=> File.mtime(logfile2) }
231
- test_session = File.open(test_session_logs.last)
232
- backwards_seek_offset = -1 * [1000, test_session.stat.size].min
233
- test_session.seek(backwards_seek_offset, IO::SEEK_END)
234
- test_session_last_messages = test_session.read
235
- end
236
-
237
- def move_test_result_bundle_for_next_run
238
- return unless @options[:result_bundle]
239
-
240
- glob_pattern = "#{output_directory}/*.test_result"
241
- preexisting_test_result_bundles = Dir.glob(glob_pattern)
242
- unnumbered_test_result_bundles = preexisting_test_result_bundles.reject do |test_result|
243
- test_result =~ /.*-\d+\.test_result/
244
- end
245
- src_test_bundle = unnumbered_test_result_bundles.first
246
- dst_test_bundle_parent_dir = File.dirname(src_test_bundle)
247
- dst_test_bundle_basename = File.basename(src_test_bundle, '.test_result')
248
- dst_test_bundle = "#{dst_test_bundle_parent_dir}/#{dst_test_bundle_basename}-#{@testrun_count}.test_result"
249
- FileUtils.mkdir_p(dst_test_bundle)
250
- FileUtils.mv(src_test_bundle, dst_test_bundle)
251
- end
252
- end
253
- end
254
- end
255
- end