Class: Fastlane::Actions::MultiScanAction
- Inherits:
-
Action
- Object
- Action
- Fastlane::Actions::MultiScanAction
- Defined in:
- lib/fastlane/plugin/test_center/actions/multi_scan.rb
Documentation collapse
- .authors ⇒ Object
- .available_options ⇒ Object
- .description ⇒ Object
- .details ⇒ Object
- .is_supported?(platform) ⇒ Boolean
- .scan_options ⇒ Object
Class Method Summary collapse
- .build_for_testing(scan_options) ⇒ Object
- .collate_reports(scan_options) ⇒ Object
- .config_has_junit_report(config) ⇒ Object
- .config_with_junit_report(config) ⇒ Object
- .increment_report_filename(filename) ⇒ Object
- .increment_report_filenames(config) ⇒ Object
- .junit_report_fileextension(config) ⇒ Object
- .junit_report_filename(config) ⇒ Object
- .junit_report_filepath(config) ⇒ Object
- .kill(program) ⇒ Object
- .quit_simulators ⇒ Object
- .remove_skipped_tests(tests_to_batch, tests_to_skip) ⇒ Object
- .run(params) ⇒ Object
- .test_products_path(derived_data_path) ⇒ Object
- .testrun_path(scan_options) ⇒ Object
- .tests_to_batch(scan_options) ⇒ Object
- .try_scan_with_retry(scan_options, maximum_try_count) ⇒ Object
- .xctest_bundle_path(xctestrun_rootpath, xctestrun_config) ⇒ Object
- .xctestrun_tests(xctestrun_path) ⇒ Object
Class Method Details
.authors ⇒ Object
276 277 278 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 276 def self. ["lyndsey-ferguson/@lyndseydf"] end |
.available_options ⇒ Object
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 251 def self. + [ FastlaneCore::ConfigItem.new( key: :try_count, env_name: "FL_MULTI_SCAN_TRY_COUNT", description: "The number of times to retry running tests via scan", type: Integer, is_string: false, default_value: 1 ), FastlaneCore::ConfigItem.new( key: :batch_count, env_name: "FL_MULTI_SCAN_BATCH_COUNT", description: "The number of test batches to run through scan. Can be combined with :try_count", type: Integer, is_string: false, default_value: 1, optional: true, verify_block: proc do |count| UI.user_error!("Error: Batch counts must be greater than zero") unless count > 0 end ) ] end |
.build_for_testing(scan_options) ⇒ Object
161 162 163 164 165 166 167 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 161 def self.build_for_testing() .delete(:test_without_building) [:build_for_testing] = true config = FastlaneCore::Configuration.create(Fastlane::Actions::ScanAction., ) Fastlane::Actions::ScanAction.run(config) [:derived_data_path] = Scan.config[:derived_data_path] end |
.collate_reports(scan_options) ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 61 def self.collate_reports() extension = junit_report_fileextension() report_files = Dir.glob("#{[:output_directory]}/*#{extension}").map do |relative_filepath| File.absolute_path(relative_filepath) end if report_files.size > 1 r = Regexp.new("^(?<filename>.*)-(\\d+)\\.(junit|xml|html)") final_report_name = junit_report_filename() match = r.match(final_report_name) if match final_report_name = "#{match[:filename]}#{extension}" end other_action.collate_junit_reports( reports: report_files.sort { |f1, f2| File.mtime(f1) <=> File.mtime(f2) }, collated_report: File.absolute_path(File.join([:output_directory], final_report_name)) ) end FileUtils.rm_f(Dir.glob("#{[:output_directory]}/*-[1-9]*#{extension}")) end |
.config_has_junit_report(config) ⇒ Object
169 170 171 172 173 174 175 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 169 def self.config_has_junit_report(config) output_types = config.fetch(:output_types, '').to_s.split(',') output_filenames = config.fetch(:output_files, '').to_s.split(',') output_type_file_count_match = output_types.size == output_filenames.size output_types.include?('junit') && (output_type_file_count_match || config[:custom_report_file_name].to_s.strip.length > 0) end |
.config_with_junit_report(config) ⇒ Object
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 177 def self.config_with_junit_report(config) return config if config_has_junit_report(config) if config[:output_types].to_s.strip.empty? || config[:custom_report_file_name] config[:custom_report_file_name] ||= 'report.xml' config[:output_types] = 'junit' elsif config[:output_types].strip == 'junit' && config[:output_files].to_s.strip.empty? config[:custom_report_file_name] ||= 'report.xml' elsif !config[:output_types].split(',').include?('junit') config[:output_types] << ',junit' config[:output_files] << ',report.xml' elsif config[:output_files].nil? config[:output_files] = config[:output_types].split(',').map { |type| "report.#{type}" }.join(',') end config end |
.description ⇒ Object
239 240 241 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 239 def self.description "Uses scan to run Xcode tests a given number of times: only re-testing failing tests." end |
.details ⇒ Object
243 244 245 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 243 def self.details "Use this action to run your tests if you have fragile tests that fail sporadically." end |
.increment_report_filename(filename) ⇒ Object
211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 211 def self.increment_report_filename(filename) new_report_number = 2 basename = File.basename(filename, '.*') r = Regexp.new("^(?<filename>.*)-(?<report_number>\\d+)\\.(junit|xml|html)") match = r.match(filename) if match new_report_number = match[:report_number].to_i + 1 basename = match[:filename] end "#{basename}-#{new_report_number}#{File.extname(filename)}" end |
.increment_report_filenames(config) ⇒ Object
223 224 225 226 227 228 229 230 231 232 233 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 223 def self.increment_report_filenames(config) if config[:output_files] output_files = config[:output_files].to_s.split(',') output_files = output_files.map do |output_file| increment_report_filename(output_file) end config[:output_files] = output_files.join(',') elsif config[:custom_report_file_name] config[:custom_report_file_name] = increment_report_filename(config[:custom_report_file_name]) end end |
.is_supported?(platform) ⇒ Boolean
280 281 282 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 280 def self.is_supported?(platform) platform == :ios end |
.junit_report_fileextension(config) ⇒ Object
203 204 205 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 203 def self.junit_report_fileextension(config) File.extname(junit_report_filename(config)) end |
.junit_report_filename(config) ⇒ Object
194 195 196 197 198 199 200 201 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 194 def self.junit_report_filename(config) report_filename = config[:custom_report_file_name] if report_filename.nil? junit_index = config[:output_types].split(',').find_index('junit') report_filename = config[:output_files].to_s.split(',')[junit_index] end report_filename end |
.junit_report_filepath(config) ⇒ Object
207 208 209 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 207 def self.junit_report_filepath(config) File.absolute_path(File.join(config[:output_directory], junit_report_filename(config))) end |
.kill(program) ⇒ Object
81 82 83 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 81 def self.kill(program) Actions.sh("killall -9 '#{program}' &> /dev/null || true", log: false) end |
.quit_simulators ⇒ Object
85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 85 def self.quit_simulators kill('iPhone Simulator') kill('Simulator') kill('SimulatorBridge') launchctl_list_count = 0 while Actions.sh('launchctl list | grep com.apple.CoreSimulator.CoreSimulatorService || true', log: false) != '' break if (launchctl_list_count += 1) > 10 Actions.sh('launchctl remove com.apple.CoreSimulator.CoreSimulatorService &> /dev/null || true', log: false) sleep(1) end end |
.remove_skipped_tests(tests_to_batch, tests_to_skip) ⇒ Object
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 111 def self.remove_skipped_tests(tests_to_batch, tests_to_skip) if tests_to_skip.nil? return tests_to_batch end if tests_to_skip tests_to_skip = tests_to_skip testsuites_to_skip = tests_to_skip.select do |testsuite| testsuite.count('/') == 1 # just the testable/testsuite end tests_to_skip -= testsuites_to_skip tests_to_batch.reject! do |test_identifier| test_suite = test_identifier.split('/').first(2).join('/') testsuites_to_skip.include?(test_suite) end tests_to_batch -= tests_to_skip end tests_to_batch end |
.run(params) ⇒ Object
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 9 def self.run(params) = params.values.reject { |k| %i[try_count batch_count].include?(k) } unless Helper.test? FastlaneCore::PrintTable.print_values( config: params._values.reject { |k, v| .key?(k) }, title: "Summary for multi_scan (test_center v#{Fastlane::TestCenter::VERSION})" ) end = config_with_junit_report() unless [:test_without_building] build_for_testing() .delete(:build_for_testing) [:test_without_building] = true end batch_count = params[:batch_count] if batch_count == 1 try_scan_with_retry(, params[:try_count]) else tests = tests_to_batch() tests.each_slice((tests.length / batch_count.to_f).round).to_a.each do |tests_batch| .reject! { |key| key == :skip_testing } [:only_testing] = tests_batch try_scan_with_retry(, params[:try_count]) end end collate_reports() end |
.scan_options ⇒ Object
247 248 249 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 247 def self. ScanAction. end |
.test_products_path(derived_data_path) ⇒ Object
157 158 159 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 157 def self.test_products_path(derived_data_path) File.join(derived_data_path, "Build", "Products") end |
.testrun_path(scan_options) ⇒ Object
153 154 155 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 153 def self.testrun_path() Dir.glob("#{[:derived_data_path]}/Build/Products/#{[:scheme]}*.xctestrun").first end |
.tests_to_batch(scan_options) ⇒ Object
98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 98 def self.tests_to_batch() unless [:only_testing].nil? return [:only_testing] end xctestrun_path = [:xctestrun] || testrun_path() if xctestrun_path.nil? || !File.exist?(xctestrun_path) UI.user_error!("Error: cannot find expected xctestrun file '#{xctestrun_path}'") end tests = xctestrun_tests(xctestrun_path) remove_skipped_tests(tests, [:skip_testing]) end |
.try_scan_with_retry(scan_options, maximum_try_count) ⇒ Object
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 41 def self.try_scan_with_retry(, maximum_try_count) try_count = 0 begin try_count += 1 config = FastlaneCore::Configuration.create(Fastlane::Actions::ScanAction., ) Fastlane::Actions::ScanAction.run(config) rescue FastlaneCore::Interface::FastlaneTestFailure => e UI.verbose("Scan failed with #{e}") if try_count < maximum_try_count report_filepath = junit_report_filepath() failed_tests = other_action.tests_from_junit(junit: report_filepath)[:failed] [:only_testing] = failed_tests.map(&:shellescape) increment_report_filenames() retry end else increment_report_filenames() end end |
.xctest_bundle_path(xctestrun_rootpath, xctestrun_config) ⇒ Object
147 148 149 150 151 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 147 def self.xctest_bundle_path(xctestrun_rootpath, xctestrun_config) xctest_host_path = xctestrun_config['TestHostPath'].sub('__TESTROOT__', xctestrun_rootpath) xctestrun_config['TestBundlePath'].sub!('__TESTHOST__', xctest_host_path) xctestrun_config['TestBundlePath'].sub('__TESTROOT__', xctestrun_rootpath) end |
.xctestrun_tests(xctestrun_path) ⇒ Object
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/fastlane/plugin/test_center/actions/multi_scan.rb', line 131 def self.xctestrun_tests(xctestrun_path) xctestrun = Plist.parse_xml(xctestrun_path) xctestrun_rootpath = File.dirname(xctestrun_path) tests = [] xctestrun.each do |testable_name, xctestrun_config| test_identifiers = XCTestList.tests(xctest_bundle_path(xctestrun_rootpath, xctestrun_config)) if xctestrun_config.key?('SkipTestIdentifiers') test_identifiers.reject! { |test_identifier| xctestrun_config['SkipTestIdentifiers'].include?(test_identifier) } end tests += test_identifiers.map do |test_identifier| "#{testable_name.shellescape}/#{test_identifier}" end end tests end |