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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7d7647dee8a9311b8e18eeba2a4afbc906d0c751
4
- data.tar.gz: 0074ac993896e002df67534365fe1e367a2bc71d
3
+ metadata.gz: 4e73880166b9ba845963df59878b80eba77ca64d
4
+ data.tar.gz: 182b6aea7cbb03dfd121efc35dc832ca85a1bb6c
5
5
  SHA512:
6
- metadata.gz: 2da85b784f6d88a4b0022c07ec3d6b2def13c1a7f47d8634ae1a665255d814de59c783ff85d39765fdc523cba1bb260200c01f314d25cff846cd946747425f7c
7
- data.tar.gz: 8fdec1723d3d712a5907c240a0121997553b3aa5750cd2eb856721d7b09e7a2f14d7358f41eb730522993508fa190e37d05e1ac34cb60249292d9eb0a853c0e4
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 = :ios if Scan.config[:destination].any? { |d| d.include?('platform=iOS Simulator') }
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
- # :nocov:
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
- # :nocov:
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
- scan_options[:xctestrun] = Dir.glob("#{Scan.config[:derived_data_path]}/Build/Products/*.xctestrun").first
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
- FileUtils.rm_f(File.join(output_directory, output_file))
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 unkown.")
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'
@@ -1,13 +1,20 @@
1
1
  module TestCenter
2
2
  module Helper
3
3
  module MultiScanManager
4
- class ParallelTestBatchWorker < TestBatchWorker
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
- puts "[worker #{@options[:batch_index] + 1}] #{line}"
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
- FastlaneCore::PrintTable.print_values(
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.message("Deleting xcresults: #{xcresults}")
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
- ENV['XCPRETTY_JSON_FILE_OUTPUT'] = File.join(
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
- if @reportnamer.includes_html?
155
- html_report_filepath = File.join(output_directory, @reportnamer.html_last_reportname)
156
- info[:html_report_filepath] = html_report_filepath
157
- end
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
- 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
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(test_operation_failure)
235
+ FastlaneCore::UI.error(failure)
208
236
  when /Lost connection to testmanagerd/
209
- FastlaneCore::UI.error(test_operation_failure)
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: 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: 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 = run_invocation_based_tests
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
- FileUtils.rm_rf(preexisting_test_result_bundles)
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 run_invocation_based_tests
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] = Fastlane::Actions::TestsFromJunitAction.run(config)[:failed]
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] == :ios
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] == :ios
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
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module TestCenter
3
- VERSION = "3.8.0.parallelizing.beta.7"
3
+ VERSION = "3.8.0.parallelizing.beta.8"
4
4
  end
5
5
  end
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.7
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-07 00:00:00.000000000 Z
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