scan/lib/scan/runner.rb in fastlane_hotfix-2.165.1 vs scan/lib/scan/runner.rb in fastlane_hotfix-2.187.0
- old
+ new
@@ -49,11 +49,18 @@
Scan.devices.each do |device|
FastlaneCore::Simulator.uninstall_app(app_identifier, device.name, device.udid)
end
end
+ execute(retries: Scan.config[:number_of_retries])
+ end
+
+ def execute(retries: 0)
+ Scan.cache[:retry_attempt] = Scan.config[:number_of_retries] - retries
+
command = @test_command_generator.generate
+
prefix_hash = [
{
prefix: "Running Tests: ",
block: proc do |value|
value.include?("Touching")
@@ -69,22 +76,75 @@
loading: "Loading...",
suppress_output: Scan.config[:suppress_xcode_output],
error: proc do |error_output|
begin
exit_status = $?.exitstatus
- ErrorHandler.handle_build_error(error_output, @test_command_generator.xcodebuild_log_path)
+ if retries > 0
+ # If there are retries remaining, run the tests again
+ return retry_execute(retries: retries, error_output: error_output)
+ else
+ ErrorHandler.handle_build_error(error_output, @test_command_generator.xcodebuild_log_path)
+ end
rescue => ex
SlackPoster.new.run({
build_errors: 1
})
raise ex
end
end)
+
exit_status
end
+ def retry_execute(retries:, error_output: "")
+ tests = retryable_tests(error_output)
+
+ if tests.empty?
+ UI.crash!("Failed to find failed tests to retry (could not parse error output)")
+ end
+
+ Scan.config[:only_testing] = tests
+ UI.important("Retrying tests: #{Scan.config[:only_testing].join(', ')}")
+
+ retries -= 1
+ UI.important("Number of retries remaining: #{retries}")
+
+ return execute(retries: retries)
+ end
+
+ def retryable_tests(input)
+ input = Helper.strip_ansi_colors(input)
+
+ retryable_tests = []
+
+ failing_tests = input.split("Failing tests:\n").fetch(1, [])
+ .split("\n\n").first
+
+ suites = failing_tests.split(/(?=\n\s+[\w\s]+:\n)/)
+
+ suites.each do |suite|
+ suite_name = suite.match(/\s*([\w\s\S]+):/).captures.first
+
+ test_cases = suite.split(":\n").fetch(1, []).split("\n").each
+ .select { |line| line.match?(/^\s+/) }
+ .map { |line| line.strip.gsub(".", "/").gsub("()", "") }
+ .map { |line| suite_name + "/" + line }
+
+ retryable_tests += test_cases
+ end
+
+ return retryable_tests.uniq
+ end
+
def handle_results(tests_exit_status)
+ if Scan.config[:disable_xcpretty]
+ unless tests_exit_status == 0
+ UI.test_failure!("Test execution failed. Exit status: #{tests_exit_status}")
+ end
+ return
+ end
+
result = TestResultParser.new.parse_result(test_results)
SlackPoster.new.run(result)
if result[:failures] > 0
failures_str = result[:failures].to_s.red
@@ -101,10 +161,11 @@
}))
puts("")
copy_simulator_logs
zip_build_products
+ copy_xctestrun
if result[:failures] > 0
open_report
UI.test_failure!("Tests have failed")
@@ -141,12 +202,36 @@
UI.message("Zipping build products")
FastlaneCore::Helper.zip_directory(path, output_path, contents_only: true, overwrite: true, print: false)
UI.message("Successfully zipped build products: #{output_path}")
end
- def test_results
- return if Scan.config[:disable_xcpretty]
+ def copy_xctestrun
+ return unless Scan.config[:output_xctestrun]
+ # Gets :derived_data_path/Build/Products directory for coping .xctestrun file
+ derived_data_path = Scan.config[:derived_data_path]
+ path = File.join(derived_data_path, "Build", "Products")
+
+ # Gets absolute path of output directory
+ output_directory = File.absolute_path(Scan.config[:output_directory])
+ output_path = File.join(output_directory, "settings.xctestrun")
+
+ # Caching path for action to put into lane_context
+ Scan.cache[:output_xctestrun] = output_path
+
+ # Copy .xctestrun file and moves it to output directory
+ UI.message("Copying .xctestrun file")
+ xctestrun_file = Dir.glob("#{path}/*.xctestrun").first
+
+ if xctestrun_file
+ FileUtils.cp(xctestrun_file, output_path)
+ UI.message("Successfully copied xctestrun file: #{output_path}")
+ else
+ UI.user_error!("Could not find .xctextrun file to copy")
+ end
+ end
+
+ def test_results
temp_junit_report = Scan.cache[:temp_junit_report]
return File.read(temp_junit_report) if temp_junit_report && File.file?(temp_junit_report)
# Something went wrong with the temp junit report for the test success/failures count.
# We'll have to regenerate from the xcodebuild log, like we did before version 2.34.0.