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.