fastlane-plugin-test_center 3.8.0.parallelizing.beta.7 → 3.8.0.parallelizing.beta.8
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/lib/fastlane/plugin/test_center/actions/multi_scan.rb +43 -32
- data/lib/fastlane/plugin/test_center/helper/multi_scan_manager.rb +7 -0
- data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/parallel_test_batch_worker.rb +25 -6
- data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/report_collator.rb +9 -0
- data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/retrying_scan.rb +1 -8
- data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/retrying_scan_helper.rb +80 -44
- data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/runner.rb +32 -5
- data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/test_batch_worker_pool.rb +3 -5
- data/lib/fastlane/plugin/test_center/helper/scan_helper.rb +13 -0
- data/lib/fastlane/plugin/test_center/helper/test_collector.rb +1 -2
- data/lib/fastlane/plugin/test_center/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e73880166b9ba845963df59878b80eba77ca64d
|
4
|
+
data.tar.gz: 182b6aea7cbb03dfd121efc35dc832ca85a1bb6c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d6998f5f5f3515b8aaf10c75a2b804e32e192088be2323ff442208034c01568c013122a8db9c602856fce420f66983eeaf3b32769b7ddcbbb522ffdbb758d86
|
7
|
+
data.tar.gz: cd1f2ff6cbe717c40564514dff042a747a082d5e82e33212cdab478c83899d788154f867d16f23964669e38a0e7231b9bc7cfee9e3c54b46ff7806fa75653cd4
|
@@ -5,27 +5,18 @@ module Fastlane
|
|
5
5
|
require 'shellwords'
|
6
6
|
require 'xctest_list'
|
7
7
|
require 'plist'
|
8
|
-
require_relative '../helper/multi_scan_manager/runner'
|
9
8
|
|
10
9
|
class MultiScanAction < Action
|
11
10
|
def self.run(params)
|
12
|
-
# :nocov:
|
13
|
-
unless Helper.test?
|
14
|
-
scan_keys = Fastlane::Actions::ScanAction.available_options.map(&:key)
|
15
|
-
FastlaneCore::PrintTable.print_values(
|
16
|
-
config: params._values.reject { |k, _| scan_keys.include?(k) },
|
17
|
-
title: "Summary for multi_scan (test_center v#{Fastlane::TestCenter::VERSION})"
|
18
|
-
)
|
19
|
-
end
|
20
|
-
# :nocov:
|
21
11
|
params[:quit_simulators] ||= params._values[:force_quit_simulator]
|
22
12
|
|
13
|
+
print_multi_scan_parameters(params)
|
23
14
|
force_quit_simulator_processes if params[:quit_simulators]
|
24
15
|
|
25
16
|
prepare_for_testing(params.values)
|
26
17
|
|
27
18
|
platform = :mac
|
28
|
-
platform = :
|
19
|
+
platform = :ios_simulator if Scan.config[:destination].any? { |d| d.include?('platform=iOS Simulator') }
|
29
20
|
|
30
21
|
runner_options = params.values.merge(platform: platform)
|
31
22
|
runner = ::TestCenter::Helper::MultiScanManager::Runner.new(runner_options)
|
@@ -35,14 +26,7 @@ module Fastlane
|
|
35
26
|
end
|
36
27
|
|
37
28
|
summary = run_summary(params, tests_passed, runner.retry_total_count)
|
38
|
-
|
39
|
-
unless Helper.test?
|
40
|
-
FastlaneCore::PrintTable.print_values(
|
41
|
-
config: summary,
|
42
|
-
title: "multi_scan results"
|
43
|
-
)
|
44
|
-
end
|
45
|
-
# :nocov:
|
29
|
+
print_run_summary(summary)
|
46
30
|
|
47
31
|
if params[:fail_build] && !tests_passed
|
48
32
|
raise UI.test_failure!('Tests have failed')
|
@@ -50,6 +34,28 @@ module Fastlane
|
|
50
34
|
summary
|
51
35
|
end
|
52
36
|
|
37
|
+
def self.print_multi_scan_parameters(params)
|
38
|
+
return if Helper.test?
|
39
|
+
# :nocov:
|
40
|
+
scan_keys = Fastlane::Actions::ScanAction.available_options.map(&:key)
|
41
|
+
FastlaneCore::PrintTable.print_values(
|
42
|
+
config: params._values.reject { |k, _| scan_keys.include?(k) },
|
43
|
+
title: "Summary for multi_scan (test_center v#{Fastlane::TestCenter::VERSION})"
|
44
|
+
)
|
45
|
+
# :nocov:
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.print_run_summary(summary)
|
49
|
+
return if Helper.test?
|
50
|
+
|
51
|
+
# :nocov:
|
52
|
+
FastlaneCore::PrintTable.print_values(
|
53
|
+
config: summary,
|
54
|
+
title: "multi_scan results"
|
55
|
+
)
|
56
|
+
# :nocov:
|
57
|
+
end
|
58
|
+
|
53
59
|
def self.run_summary(scan_options, tests_passed, retry_total_count)
|
54
60
|
reportnamer = ::TestCenter::Helper::ReportNameHelper.new(
|
55
61
|
scan_options[:output_types],
|
@@ -98,8 +104,10 @@ module Fastlane
|
|
98
104
|
|
99
105
|
def self.prepare_for_testing(scan_options)
|
100
106
|
if scan_options[:test_without_building] || scan_options[:skip_build]
|
107
|
+
UI.verbose("Preparing Scan config options for multi_scan testing")
|
101
108
|
prepare_scan_config(scan_options)
|
102
109
|
else
|
110
|
+
UI.verbose("Building the project in preparation for multi_scan testing")
|
103
111
|
build_for_testing(scan_options)
|
104
112
|
end
|
105
113
|
end
|
@@ -113,15 +121,7 @@ module Fastlane
|
|
113
121
|
|
114
122
|
def self.build_for_testing(scan_options)
|
115
123
|
values = prepare_scan_options_for_build_for_testing(scan_options)
|
116
|
-
|
117
|
-
unless Helper.test?
|
118
|
-
FastlaneCore::PrintTable.print_values(
|
119
|
-
config: values,
|
120
|
-
hide_keys: [:destination, :slack_url],
|
121
|
-
title: "Summary for scan #{Fastlane::VERSION}"
|
122
|
-
)
|
123
|
-
end
|
124
|
-
# :nocov:
|
124
|
+
ScanHelper.print_scan_parameters(values)
|
125
125
|
|
126
126
|
remove_preexisting_xctestrun_files
|
127
127
|
Scan::Runner.new.run
|
@@ -146,21 +146,30 @@ module Fastlane
|
|
146
146
|
end
|
147
147
|
|
148
148
|
def self.update_xctestrun_after_build(scan_options)
|
149
|
-
|
149
|
+
xctestrun_files = Dir.glob("#{Scan.config[:derived_data_path]}/Build/Products/*.xctestrun")
|
150
|
+
UI.verbose("After building, found xctestrun files #{xctestrun_files} (choosing 1st)")
|
151
|
+
scan_options[:xctestrun] = xctestrun_files.first
|
150
152
|
end
|
151
153
|
|
152
154
|
def self.remove_preexisting_xctestrun_files
|
153
155
|
xctestrun_files = Dir.glob("#{Scan.config[:derived_data_path]}/Build/Products/*.xctestrun")
|
156
|
+
UI.verbose("Before building, removing pre-existing xctestrun files: #{xctestrun_files}")
|
154
157
|
FileUtils.rm_rf(xctestrun_files)
|
155
158
|
end
|
156
159
|
|
157
160
|
def self.remove_build_report_files
|
161
|
+
# When Scan builds, it generates empty report files. Trying to collate
|
162
|
+
# subsequent, valid, report files with the empty report file will fail
|
163
|
+
# because there is no shared XML elements
|
158
164
|
report_options = Scan::XCPrettyReporterOptionsGenerator.generate_from_scan_config
|
159
165
|
output_files = report_options.instance_variable_get(:@output_files)
|
160
166
|
output_directory = report_options.instance_variable_get(:@output_directory)
|
161
167
|
|
168
|
+
UI.verbose("Removing report files generated by the build")
|
162
169
|
output_files.each do |output_file|
|
163
|
-
|
170
|
+
report_file = File.join(output_directory, output_file)
|
171
|
+
UI.verbose(" #{report_file}")
|
172
|
+
FileUtils.rm_f(report_file)
|
164
173
|
end
|
165
174
|
end
|
166
175
|
|
@@ -198,6 +207,8 @@ module Fastlane
|
|
198
207
|
end
|
199
208
|
|
200
209
|
def self.scan_options
|
210
|
+
# multi_scan has its own enhanced version of `output_types` and we want to provide
|
211
|
+
# the help and validation for that new version.
|
201
212
|
ScanAction.available_options.reject { |config| %i[output_types].include?(config.key) }
|
202
213
|
end
|
203
214
|
|
@@ -234,7 +245,7 @@ module Fastlane
|
|
234
245
|
conflict_block: proc do |value|
|
235
246
|
UI.user_error!(
|
236
247
|
"Error: Can't use 'invocation_based_tests' and 'batch_count' options in one run, "\
|
237
|
-
"because the number of tests is
|
248
|
+
"because the number of tests is unknown")
|
238
249
|
end
|
239
250
|
),
|
240
251
|
FastlaneCore::ConfigItem.new(
|
@@ -272,7 +283,7 @@ module Fastlane
|
|
272
283
|
),
|
273
284
|
FastlaneCore::ConfigItem.new(
|
274
285
|
key: :testrun_completed_block,
|
275
|
-
description: 'A block invoked each time a test run completes',
|
286
|
+
description: 'A block invoked each time a test run completes. When combined with :parallel_testrun_count, will be called separately in each child process',
|
276
287
|
optional: true,
|
277
288
|
is_string: false,
|
278
289
|
default_value: nil,
|
@@ -1,3 +1,10 @@
|
|
1
|
+
require_relative 'multi_scan_manager/device_manager'
|
2
|
+
require_relative 'multi_scan_manager/parallel_test_batch_worker'
|
1
3
|
require_relative 'multi_scan_manager/report_collator'
|
4
|
+
require_relative 'multi_scan_manager/retrying_scan_helper.rb'
|
5
|
+
require_relative 'multi_scan_manager/retrying_scan'
|
2
6
|
require_relative 'multi_scan_manager/runner'
|
7
|
+
require_relative 'multi_scan_manager/simulator_helper'
|
8
|
+
require_relative 'multi_scan_manager/test_batch_worker_pool'
|
9
|
+
require_relative 'multi_scan_manager/test_batch_worker'
|
3
10
|
require_relative 'xctestrun_info'
|
data/lib/fastlane/plugin/test_center/helper/multi_scan_manager/parallel_test_batch_worker.rb
CHANGED
@@ -1,13 +1,20 @@
|
|
1
1
|
module TestCenter
|
2
2
|
module Helper
|
3
3
|
module MultiScanManager
|
4
|
-
|
4
|
+
require 'colorize'
|
5
5
|
|
6
|
+
|
7
|
+
class ParallelTestBatchWorker < TestBatchWorker
|
8
|
+
|
6
9
|
attr_reader :pid
|
7
|
-
|
10
|
+
|
8
11
|
def initialize(options)
|
9
12
|
super(options)
|
10
13
|
@pipe_endpoint = nil
|
14
|
+
|
15
|
+
@@colors ||= String.colors - %i[white black light_green default]
|
16
|
+
@color = @@colors.sample
|
17
|
+
@@colors = @@colors - [@color]
|
11
18
|
end
|
12
19
|
|
13
20
|
def state=(new_state)
|
@@ -15,9 +22,16 @@ module TestCenter
|
|
15
22
|
end
|
16
23
|
|
17
24
|
def process_results
|
25
|
+
# This is performed in the Parent process
|
18
26
|
@pid = nil
|
27
|
+
|
28
|
+
worker_prefix = "[worker #{@options[:batch_index] + 1}] "
|
19
29
|
File.foreach(@log_filepath) do |line|
|
20
|
-
|
30
|
+
unless FastlaneCore::Helper.colors_disabled?
|
31
|
+
worker_prefix = worker_prefix.colorize(@color)
|
32
|
+
end
|
33
|
+
print worker_prefix
|
34
|
+
print line
|
21
35
|
end
|
22
36
|
state = :ready_to_work
|
23
37
|
@options[:test_batch_results] << (@reader.gets == 'true')
|
@@ -44,6 +58,11 @@ module TestCenter
|
|
44
58
|
end
|
45
59
|
|
46
60
|
def open_interprocess_communication
|
61
|
+
# This is performed in the Parent process in preparation to setup
|
62
|
+
# the STDOUT and STDOUT for printing messages from the Child process
|
63
|
+
# to a file. This is done so that when multiple processes write
|
64
|
+
# messages, they will not be written to the console in a broken
|
65
|
+
# interlaced manner.
|
47
66
|
@reader, @writer = IO.pipe
|
48
67
|
@log_filepath = File.join(
|
49
68
|
Dir.mktmpdir,
|
@@ -52,7 +71,8 @@ module TestCenter
|
|
52
71
|
end
|
53
72
|
|
54
73
|
def reroute_stdout_to_logfile
|
55
|
-
@reader.close # we are now in the subprocess
|
74
|
+
@reader.close # we are now in the subprocess. Write all stdout to the
|
75
|
+
# log file to prevent interlaced messages
|
56
76
|
@logfile = File.open(@log_filepath, 'w')
|
57
77
|
@logfile.sync = true
|
58
78
|
$stdout.reopen(@logfile)
|
@@ -60,6 +80,7 @@ module TestCenter
|
|
60
80
|
end
|
61
81
|
|
62
82
|
def handle_child_process_results(tests_passed)
|
83
|
+
# as suggested by the method name, this is done in the Child process
|
63
84
|
@logfile.close
|
64
85
|
@writer.puts tests_passed.to_s
|
65
86
|
@writer.close
|
@@ -72,5 +93,3 @@ module TestCenter
|
|
72
93
|
end
|
73
94
|
end
|
74
95
|
end
|
75
|
-
|
76
|
-
|
@@ -17,6 +17,7 @@ module TestCenter
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def collate
|
20
|
+
FastlaneCore::UI.verbose("ReportCollator collating")
|
20
21
|
collate_junit_reports
|
21
22
|
collate_html_reports
|
22
23
|
collate_json_reports
|
@@ -46,6 +47,7 @@ module TestCenter
|
|
46
47
|
report_files = sort_globbed_files(glob)
|
47
48
|
collated_file = File.absolute_path(File.join(@output_directory, @reportnamer.junit_reportname(@suffix)))
|
48
49
|
if report_files.size > 1
|
50
|
+
FastlaneCore::UI.verbose("Collating junit report files #{report_files}")
|
49
51
|
config = create_config(
|
50
52
|
CollateJunitReportsAction,
|
51
53
|
{
|
@@ -56,6 +58,7 @@ module TestCenter
|
|
56
58
|
CollateJunitReportsAction.run(config)
|
57
59
|
FileUtils.rm_rf(report_files - [collated_file])
|
58
60
|
elsif report_files.size == 1 && report_files.first != collated_file
|
61
|
+
FastlaneCore::UI.verbose("Copying junit report file #{report_files.first}")
|
59
62
|
FileUtils.mkdir_p(File.dirname(collated_file))
|
60
63
|
FileUtils.mv(report_files.first, collated_file)
|
61
64
|
end
|
@@ -67,6 +70,7 @@ module TestCenter
|
|
67
70
|
report_files = sort_globbed_files("#{@source_reports_directory_glob}/#{@reportnamer.html_fileglob}")
|
68
71
|
collated_file = File.absolute_path(File.join(@output_directory, @reportnamer.html_reportname(@suffix)))
|
69
72
|
if report_files.size > 1
|
73
|
+
FastlaneCore::UI.verbose("Collating html report files #{report_files}")
|
70
74
|
config = create_config(
|
71
75
|
CollateJunitReportsAction,
|
72
76
|
{
|
@@ -77,6 +81,7 @@ module TestCenter
|
|
77
81
|
CollateHtmlReportsAction.run(config)
|
78
82
|
FileUtils.rm_rf(report_files - [collated_file])
|
79
83
|
elsif report_files.size == 1 && report_files.first != collated_file
|
84
|
+
FastlaneCore::UI.verbose("Copying html report file #{report_files.first}")
|
80
85
|
FileUtils.mkdir_p(File.dirname(collated_file))
|
81
86
|
FileUtils.mv(report_files.first, collated_file)
|
82
87
|
end
|
@@ -88,6 +93,7 @@ module TestCenter
|
|
88
93
|
report_files = sort_globbed_files("#{@source_reports_directory_glob}/#{@reportnamer.json_fileglob}")
|
89
94
|
collated_file = File.absolute_path(File.join(@output_directory, @reportnamer.json_reportname(@suffix)))
|
90
95
|
if report_files.size > 1
|
96
|
+
FastlaneCore::UI.verbose("Collating json report files #{report_files}")
|
91
97
|
config = create_config(
|
92
98
|
CollateJsonReportsAction,
|
93
99
|
{
|
@@ -98,6 +104,7 @@ module TestCenter
|
|
98
104
|
CollateJsonReportsAction.run(config)
|
99
105
|
FileUtils.rm_rf(report_files - [collated_file])
|
100
106
|
elsif report_files.size == 1 && report_files.first != collated_file
|
107
|
+
FastlaneCore::UI.verbose("Copying json report file #{report_files.first}")
|
101
108
|
FileUtils.mkdir_p(File.dirname(collated_file))
|
102
109
|
FileUtils.mv(report_files.first, collated_file)
|
103
110
|
end
|
@@ -109,6 +116,7 @@ module TestCenter
|
|
109
116
|
test_result_bundlepaths = sort_globbed_files("#{@source_reports_directory_glob}/#{@scheme}*.test_result")
|
110
117
|
collated_test_result_bundlepath = File.absolute_path("#{File.join(@output_directory, @scheme)}.test_result")
|
111
118
|
if test_result_bundlepaths.size > 1
|
119
|
+
FastlaneCore::UI.verbose("Collating test_result bundles #{test_result_bundlepaths}")
|
112
120
|
config = create_config(
|
113
121
|
CollateTestResultBundlesAction,
|
114
122
|
{
|
@@ -119,6 +127,7 @@ module TestCenter
|
|
119
127
|
CollateTestResultBundlesAction.run(config)
|
120
128
|
FileUtils.rm_rf(test_result_bundlepaths - [collated_test_result_bundlepath])
|
121
129
|
elsif test_result_bundlepaths.size == 1 && test_result_bundlepaths.first != collated_test_result_bundlepath
|
130
|
+
FastlaneCore::UI.verbose("Copying test_result bundle #{test_result_bundlepaths.first}")
|
122
131
|
FileUtils.mkdir_p(File.dirname(collated_test_result_bundlepath))
|
123
132
|
FileUtils.mv(test_result_bundlepaths.first, collated_test_result_bundlepath)
|
124
133
|
end
|
@@ -44,28 +44,21 @@ module TestCenter
|
|
44
44
|
def run
|
45
45
|
try_count = @options[:try_count] || 1
|
46
46
|
begin
|
47
|
-
# TODO move delete_xcresults to `before_testrun`
|
48
47
|
@retrying_scan_helper.before_testrun
|
49
48
|
update_scan_options
|
50
49
|
|
51
50
|
values = scan_config.values(ask: false)
|
52
51
|
values[:xcode_path] = File.expand_path("../..", FastlaneCore::Helper.xcode_path)
|
53
|
-
|
54
|
-
config: values,
|
55
|
-
hide_keys: [:destination, :slack_url],
|
56
|
-
title: "Summary for scan #{Fastlane::VERSION}"
|
57
|
-
) unless FastlaneCore::Helper.test?
|
52
|
+
ScanHelper.print_scan_parameters(values)
|
58
53
|
|
59
54
|
Scan::Runner.new.run
|
60
55
|
@retrying_scan_helper.after_testrun
|
61
56
|
true
|
62
57
|
rescue FastlaneCore::Interface::FastlaneTestFailure => e
|
63
|
-
FastlaneCore::UI.message("retrying_scan after test failure")
|
64
58
|
@retrying_scan_helper.after_testrun(e)
|
65
59
|
retry if @retrying_scan_helper.testrun_count < try_count
|
66
60
|
false
|
67
61
|
rescue FastlaneCore::Interface::FastlaneBuildFailure => e
|
68
|
-
FastlaneCore::UI.message("retrying_scan after build failure")
|
69
62
|
@retrying_scan_helper.after_testrun(e)
|
70
63
|
retry if @retrying_scan_helper.testrun_count < try_count
|
71
64
|
false
|
@@ -1,8 +1,6 @@
|
|
1
1
|
module TestCenter
|
2
2
|
module Helper
|
3
3
|
module MultiScanManager
|
4
|
-
require_relative 'device_manager'
|
5
|
-
|
6
4
|
class RetryingScanHelper
|
7
5
|
|
8
6
|
attr_reader :testrun_count
|
@@ -19,7 +17,7 @@ module TestCenter
|
|
19
17
|
@options[:custom_report_file_name]
|
20
18
|
)
|
21
19
|
end
|
22
|
-
|
20
|
+
|
23
21
|
def before_testrun
|
24
22
|
delete_xcresults # has to be performed _after_ moving a *.test_result
|
25
23
|
quit_simulator
|
@@ -32,7 +30,9 @@ module TestCenter
|
|
32
30
|
|
33
31
|
@options.fetch(:destination).each do |destination|
|
34
32
|
if /id=(?<udid>\w+),?/ =~ destination
|
33
|
+
FastlaneCore::UI.verbose("Restarting Simulator #{udid}")
|
35
34
|
`xcrun simctl shutdown #{udid} 2>/dev/null`
|
35
|
+
`xcrun simctl boot #{udid} 2>/dev/null`
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
@@ -40,7 +40,10 @@ module TestCenter
|
|
40
40
|
def delete_xcresults
|
41
41
|
derived_data_path = File.expand_path(@options[:derived_data_path] || Scan.config[:derived_data_path])
|
42
42
|
xcresults = Dir.glob("#{derived_data_path}/Logs/Test/*.xcresult")
|
43
|
-
FastlaneCore::UI.
|
43
|
+
FastlaneCore::UI.verbose("Deleting xcresults:")
|
44
|
+
xcresults.each do |xcresult|
|
45
|
+
FastlaneCore::UI.verbose(" #{xcresult}")
|
46
|
+
end
|
44
47
|
FileUtils.rm_rf(xcresults)
|
45
48
|
end
|
46
49
|
|
@@ -61,10 +64,12 @@ module TestCenter
|
|
61
64
|
def set_json_env
|
62
65
|
return unless @reportnamer.includes_json?
|
63
66
|
|
64
|
-
|
67
|
+
xcpretty_json_file_output = File.join(
|
65
68
|
output_directory,
|
66
69
|
@reportnamer.json_last_reportname
|
67
70
|
)
|
71
|
+
FastlaneCore::UI.verbose("Setting the XCPRETTY_JSON_FILE_OUTPUT to #{xcpretty_json_file_output}")
|
72
|
+
ENV['XCPRETTY_JSON_FILE_OUTPUT'] = xcpretty_json_file_output
|
68
73
|
end
|
69
74
|
|
70
75
|
def reset_json_env
|
@@ -91,10 +96,22 @@ module TestCenter
|
|
91
96
|
def after_testrun(exception = nil)
|
92
97
|
@testrun_count = @testrun_count + 1
|
93
98
|
if exception.kind_of?(FastlaneCore::Interface::FastlaneTestFailure)
|
99
|
+
after_testrun_message = "Scan found failing tests"
|
100
|
+
after_testrun_message << " for batch ##{@options[:batch]}" unless @options[:batch].nil?
|
101
|
+
FastlaneCore::UI.verbose(after_testrun_message)
|
102
|
+
|
94
103
|
handle_test_failure
|
95
104
|
elsif exception.kind_of?(FastlaneCore::Interface::FastlaneBuildFailure)
|
105
|
+
after_testrun_message = "Scan unable to test"
|
106
|
+
after_testrun_message << " for batch ##{@options[:batch]}" unless @options[:batch].nil?
|
107
|
+
FastlaneCore::UI.verbose(after_testrun_message)
|
108
|
+
|
96
109
|
handle_build_failure(exception)
|
97
110
|
else
|
111
|
+
after_testrun_message = "Scan passed the tests"
|
112
|
+
after_testrun_message << " for batch ##{@options[:batch]}" unless @options[:batch].nil?
|
113
|
+
FastlaneCore::UI.verbose(after_testrun_message)
|
114
|
+
|
98
115
|
handle_success
|
99
116
|
end
|
100
117
|
collate_reports
|
@@ -130,18 +147,7 @@ module TestCenter
|
|
130
147
|
return unless @options[:testrun_completed_block]
|
131
148
|
|
132
149
|
report_filepath = nil
|
133
|
-
junit_results =
|
134
|
-
unless additional_info.key?(:test_operation_failure)
|
135
|
-
report_filepath = File.join(output_directory, @reportnamer.junit_last_reportname)
|
136
|
-
|
137
|
-
config = FastlaneCore::Configuration.create(
|
138
|
-
Fastlane::Actions::TestsFromJunitAction.available_options,
|
139
|
-
{
|
140
|
-
junit: File.absolute_path(report_filepath)
|
141
|
-
}
|
142
|
-
)
|
143
|
-
junit_results = Fastlane::Actions::TestsFromJunitAction.run(config)
|
144
|
-
end
|
150
|
+
junit_results, report_filepath = failure_details(additional_info)
|
145
151
|
|
146
152
|
info = {
|
147
153
|
failed: junit_results[:failed],
|
@@ -151,23 +157,51 @@ module TestCenter
|
|
151
157
|
report_filepath: report_filepath
|
152
158
|
}.merge(additional_info)
|
153
159
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
if @reportnamer.includes_json?
|
159
|
-
json_report_filepath = File.join(output_directory, @reportnamer.json_last_reportname)
|
160
|
-
info[:json_report_filepath] = json_report_filepath
|
161
|
-
end
|
162
|
-
if @options[:result_bundle]
|
163
|
-
test_result_suffix = '.test_result'
|
164
|
-
test_result_suffix.prepend("-#{@reportnamer.report_count}") unless @reportnamer.report_count.zero?
|
165
|
-
test_result_bundlepath = File.join(output_directory, @options[:scheme]) + test_result_suffix
|
166
|
-
info[:test_result_bundlepath] = test_result_bundlepath
|
167
|
-
end
|
160
|
+
update_html_failure_details(info)
|
161
|
+
update_json_failure_details(info)
|
162
|
+
update_test_result_bundle_details(info)
|
163
|
+
|
168
164
|
@options[:testrun_completed_block].call(info)
|
169
165
|
end
|
170
166
|
|
167
|
+
def failure_details(additional_info)
|
168
|
+
return [{}, nil] if additional_info.key?(:test_operation_failure)
|
169
|
+
|
170
|
+
report_filepath = File.join(output_directory, @reportnamer.junit_last_reportname)
|
171
|
+
config = FastlaneCore::Configuration.create(
|
172
|
+
Fastlane::Actions::TestsFromJunitAction.available_options,
|
173
|
+
{
|
174
|
+
junit: File.absolute_path(report_filepath)
|
175
|
+
}
|
176
|
+
)
|
177
|
+
junit_results = Fastlane::Actions::TestsFromJunitAction.run(config)
|
178
|
+
|
179
|
+
[junit_results, report_filepath]
|
180
|
+
end
|
181
|
+
|
182
|
+
def update_html_failure_details(info)
|
183
|
+
return unless @reportnamer.includes_html?
|
184
|
+
|
185
|
+
html_report_filepath = File.join(output_directory, @reportnamer.html_last_reportname)
|
186
|
+
info[:html_report_filepath] = html_report_filepath
|
187
|
+
end
|
188
|
+
|
189
|
+
def update_json_failure_details(info)
|
190
|
+
return unless @reportnamer.includes_json?
|
191
|
+
|
192
|
+
json_report_filepath = File.join(output_directory, @reportnamer.json_last_reportname)
|
193
|
+
info[:json_report_filepath] = json_report_filepath
|
194
|
+
end
|
195
|
+
|
196
|
+
def update_test_result_bundle_details(info)
|
197
|
+
return unless @options[:result_bundle]
|
198
|
+
|
199
|
+
test_result_suffix = '.test_result'
|
200
|
+
test_result_suffix.prepend("-#{@reportnamer.report_count}") unless @reportnamer.report_count.zero?
|
201
|
+
test_result_bundlepath = File.join(output_directory, @options[:scheme]) + test_result_suffix
|
202
|
+
info[:test_result_bundlepath] = test_result_bundlepath
|
203
|
+
end
|
204
|
+
|
171
205
|
def update_scan_options
|
172
206
|
update_only_testing
|
173
207
|
turn_off_code_coverage
|
@@ -193,30 +227,32 @@ module TestCenter
|
|
193
227
|
end
|
194
228
|
end
|
195
229
|
|
196
|
-
def handle_build_failure(exception)
|
197
|
-
test_operation_failure = ''
|
198
|
-
|
230
|
+
def handle_build_failure(exception)
|
199
231
|
test_session_last_messages = last_lines_of_test_session_log
|
200
|
-
|
201
|
-
|
202
|
-
test_operation_failure = 'Unknown test operation failure'
|
203
|
-
end
|
204
|
-
|
205
|
-
case test_operation_failure
|
232
|
+
failure = retrieve_test_operation_failure(test_session_last_messages)
|
233
|
+
case failure
|
206
234
|
when /Test runner exited before starting test execution/
|
207
|
-
FastlaneCore::UI.error(
|
235
|
+
FastlaneCore::UI.error(failure)
|
208
236
|
when /Lost connection to testmanagerd/
|
209
|
-
FastlaneCore::UI.error(
|
237
|
+
FastlaneCore::UI.error(failure)
|
210
238
|
FastlaneCore::UI.important("com.apple.CoreSimulator.CoreSimulatorService may have become corrupt, consider quitting it")
|
211
239
|
if @options[:quit_core_simulator_service]
|
212
240
|
Fastlane::Actions::RestartCoreSimulatorServiceAction.run
|
213
241
|
end
|
214
242
|
else
|
215
243
|
FastlaneCore::UI.error(test_session_last_messages)
|
216
|
-
send_callback_testrun_info(test_operation_failure:
|
244
|
+
send_callback_testrun_info(test_operation_failure: failure)
|
217
245
|
raise exception
|
218
246
|
end
|
219
|
-
send_callback_testrun_info(test_operation_failure:
|
247
|
+
send_callback_testrun_info(test_operation_failure: failure)
|
248
|
+
end
|
249
|
+
|
250
|
+
def retrieve_test_operation_failure(test_session_last_messages)
|
251
|
+
test_operation_failure_match = /Test operation failure: (?<test_operation_failure>.*)$/ =~ test_session_last_messages
|
252
|
+
if test_operation_failure_match.nil?
|
253
|
+
test_operation_failure = 'Unknown test operation failure'
|
254
|
+
end
|
255
|
+
test_operation_failure
|
220
256
|
end
|
221
257
|
|
222
258
|
def last_lines_of_test_session_log
|
@@ -44,7 +44,7 @@ module TestCenter
|
|
44
44
|
|
45
45
|
tests_passed = false
|
46
46
|
if @options[:invocation_based_tests] && @options[:only_testing].nil?
|
47
|
-
tests_passed =
|
47
|
+
tests_passed = run_first_run_of_invocation_based_tests
|
48
48
|
end
|
49
49
|
|
50
50
|
unless tests_passed || @options[:try_count] < 1
|
@@ -58,14 +58,24 @@ module TestCenter
|
|
58
58
|
|
59
59
|
glob_pattern = "#{output_directory}/**/*.test_result"
|
60
60
|
preexisting_test_result_bundles = Dir.glob(glob_pattern)
|
61
|
-
|
61
|
+
if preexisting_test_result_bundles.size > 0
|
62
|
+
FastlaneCore::UI.verbose("Removing pre-existing test_result bundles: ")
|
63
|
+
preexisting_test_result_bundles.each do |test_result_bundle|
|
64
|
+
FastlaneCore::UI.verbose(" #{test_result_bundle}")
|
65
|
+
end
|
66
|
+
FileUtils.rm_rf(preexisting_test_result_bundles)
|
67
|
+
end
|
62
68
|
end
|
63
69
|
|
64
|
-
def
|
70
|
+
def run_first_run_of_invocation_based_tests
|
71
|
+
FastlaneCore::UI.verbose("Running invocation tests")
|
65
72
|
@options[:skip_testing] = @options[:skip_testing]&.map(&:strip_testcase)&.uniq
|
66
73
|
@options[:output_directory] = output_directory
|
67
74
|
@options[:destination] = Scan.config[:destination]
|
68
75
|
|
76
|
+
# We do not want Scan.config to _not_ have :device :devices, we want to
|
77
|
+
# use :destination. We remove :force_quit_simulator as we do not want
|
78
|
+
# Scan to handle it as multi_scan takes care of it in its own way
|
69
79
|
options = @options.reject { |key| %i[device devices force_quit_simulator].include?(key) }
|
70
80
|
options[:try_count] = 1
|
71
81
|
|
@@ -84,12 +94,28 @@ module TestCenter
|
|
84
94
|
junit: File.absolute_path(report_filepath)
|
85
95
|
}
|
86
96
|
)
|
87
|
-
@options[:only_testing] =
|
97
|
+
@options[:only_testing] = retrieve_failed_invocation_tests[:failed]
|
88
98
|
@options[:only_testing] = @options[:only_testing].map(&:strip_testcase).uniq
|
89
99
|
|
90
100
|
tests_passed
|
91
101
|
end
|
92
102
|
|
103
|
+
def retrieve_failed_invocation_tests
|
104
|
+
reportnamer = ReportNameHelper.new(
|
105
|
+
@options[:output_types],
|
106
|
+
@options[:output_files],
|
107
|
+
@options[:custom_report_file_name]
|
108
|
+
)
|
109
|
+
report_filepath = File.join(output_directory, reportnamer.junit_last_reportname)
|
110
|
+
config = FastlaneCore::Configuration.create(
|
111
|
+
Fastlane::Actions::TestsFromJunitAction.available_options,
|
112
|
+
{
|
113
|
+
junit: File.absolute_path(report_filepath)
|
114
|
+
}
|
115
|
+
)
|
116
|
+
Fastlane::Actions::TestsFromJunitAction.run(config)
|
117
|
+
end
|
118
|
+
|
93
119
|
def run_test_batches
|
94
120
|
test_batch_results = []
|
95
121
|
pool_options = @options.reject { |key| %i[device devices force_quit_simulator].include?(key) }
|
@@ -141,6 +167,8 @@ module TestCenter
|
|
141
167
|
end
|
142
168
|
|
143
169
|
def collate_batched_reports_for_testable(testable)
|
170
|
+
FastlaneCore::UI.verbose("Collating results for all batches")
|
171
|
+
|
144
172
|
absolute_output_directory = File.join(
|
145
173
|
File.absolute_path(output_directory),
|
146
174
|
testable
|
@@ -169,4 +197,3 @@ module TestCenter
|
|
169
197
|
end
|
170
198
|
end
|
171
199
|
end
|
172
|
-
|
@@ -19,7 +19,7 @@ module TestCenter
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def setup_cloned_simulators
|
22
|
-
return [] unless @options[:platform] == :
|
22
|
+
return [] unless @options[:platform] == :ios_simulator
|
23
23
|
|
24
24
|
@simhelper = SimulatorHelper.new(
|
25
25
|
parallel_testrun_count: @options[:parallel_testrun_count]
|
@@ -38,7 +38,7 @@ module TestCenter
|
|
38
38
|
|
39
39
|
def destination_for_worker(worker_index)
|
40
40
|
# each worker has its own simulators to work with
|
41
|
-
return @options[:destination] unless @options[:platform] == :
|
41
|
+
return @options[:destination] unless @options[:platform] == :ios_simulator
|
42
42
|
|
43
43
|
@clones[worker_index].map do |simulator|
|
44
44
|
"platform=iOS Simulator,id=#{simulator.udid}"
|
@@ -85,9 +85,7 @@ module TestCenter
|
|
85
85
|
def setup_serial_workers
|
86
86
|
serial_scan_options = @options.reject { |key| %i[device devices].include?(key) }
|
87
87
|
serial_scan_options[:destination] ||= Scan&.config&.fetch(:destination)
|
88
|
-
@workers = [
|
89
|
-
TestBatchWorker.new(serial_scan_options)
|
90
|
-
]
|
88
|
+
@workers = [ TestBatchWorker.new(serial_scan_options) ]
|
91
89
|
end
|
92
90
|
|
93
91
|
def wait_for_worker
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module ScanHelper
|
2
|
+
def self.print_scan_parameters(params)
|
3
|
+
return if FastlaneCore::Helper.test?
|
4
|
+
|
5
|
+
# :nocov:
|
6
|
+
FastlaneCore::PrintTable.print_values(
|
7
|
+
config: params,
|
8
|
+
hide_keys: [:destination, :slack_url],
|
9
|
+
title: "Summary for scan #{Fastlane::VERSION}"
|
10
|
+
)
|
11
|
+
# :nocov:
|
12
|
+
end
|
13
|
+
end
|
@@ -31,8 +31,7 @@ module TestCenter
|
|
31
31
|
|
32
32
|
def derived_testrun_path(derived_data_path, scheme)
|
33
33
|
xctestrun_files = Dir.glob("#{derived_data_path}/Build/Products/*.xctestrun")
|
34
|
-
xctestrun_files.sort { |f1, f2| File.mtime(f1) <=> File.mtime(f2) }
|
35
|
-
.last
|
34
|
+
xctestrun_files.sort { |f1, f2| File.mtime(f1) <=> File.mtime(f2) }.last
|
36
35
|
end
|
37
36
|
|
38
37
|
def testables
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fastlane-plugin-test_center
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.8.0.parallelizing.beta.
|
4
|
+
version: 3.8.0.parallelizing.beta.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lyndsey Ferguson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-07-
|
11
|
+
date: 2019-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -267,6 +267,7 @@ files:
|
|
267
267
|
- lib/fastlane/plugin/test_center/helper/multi_scan_manager/test_batch_worker.rb
|
268
268
|
- lib/fastlane/plugin/test_center/helper/multi_scan_manager/test_batch_worker_pool.rb
|
269
269
|
- lib/fastlane/plugin/test_center/helper/reportname_helper.rb
|
270
|
+
- lib/fastlane/plugin/test_center/helper/scan_helper.rb
|
270
271
|
- lib/fastlane/plugin/test_center/helper/test_collector.rb
|
271
272
|
- lib/fastlane/plugin/test_center/helper/xcodebuild_string.rb
|
272
273
|
- lib/fastlane/plugin/test_center/helper/xctestrun_info.rb
|