diff --git a/trainer/lib/trainer/test_parser.rb b/trainer/lib/trainer/test_parser.rb index c973043d290..2d1209948a5 100644 --- a/trainer/lib/trainer/test_parser.rb +++ b/trainer/lib/trainer/test_parser.rb @@ -267,19 +267,17 @@ def summaries_to_data(summaries, failures, output_remove_retry_attempts: false) end info[:retry_count] = retry_count - # Set failure message if failure found - failure = test.find_failure(failures) - if failure + case test.test_status + when "Failure" test_row[:failures] = [{ file_name: "", line_number: 0, message: "", performance_failure: {}, - failure_message: failure.failure_message + failure_message: test.failure_message(failures) }] - info[:failure_count] += 1 - elsif test.test_status == "Skipped" + when "Skipped" test_row[:skipped] = true info[:skip_count] += 1 else diff --git a/trainer/lib/trainer/xcresult.rb b/trainer/lib/trainer/xcresult.rb index 934fabd97a2..7f6a64a6fc6 100644 --- a/trainer/lib/trainer/xcresult.rb +++ b/trainer/lib/trainer/xcresult.rb @@ -172,29 +172,11 @@ def all_subtests return [self] end - def find_failure(failures) - sanitizer = proc { |name| name.gsub(/\W/, "_") } - sanitized_identifier = sanitizer.call(self.identifier) - if self.test_status == "Failure" - # Tries to match failure on test case name - # Example TestFailureIssueSummary: - # producingTarget: "TestThisDude" - # test_case_name: "TestThisDude.testFailureJosh2()" (when Swift) - # or "-[TestThisDudeTests testFailureJosh2]" (when Objective-C) - # Example ActionTestMetadata - # identifier: "TestThisDude/testFailureJosh2()" (when Swift) - # or identifier: "TestThisDude/testFailureJosh2" (when Objective-C) - - found_failure = failures.find do |failure| - # Sanitize both test case name and identifier in a consistent fashion, then replace all non-word - # chars with underscore, and compare them - sanitized_test_case_name = sanitizer.call(failure.test_case_name) - sanitized_identifier == sanitized_test_case_name - end - return found_failure - else - return nil + def failure_message(failures) + found = failures.find do |failure| + self.identifier == failure.normalized_name end + return found ? found.failure_message : "unknown failure message" end end @@ -385,6 +367,21 @@ def initialize(data) super end + def normalized_name + # Return test_case_name normalized to match the identifier from ActionTestMetadata + # Example TestFailureIssueSummary: + # producingTarget: "TestThisDude" + # test_case_name: "TestThisDude.testFailureJosh2()" (when Swift) + # or "-[TestThisDudeTests testFailureJosh2]" (when Objective-C) + # Example ActionTestMetadata + # identifier: "TestThisDude/testFailureJosh2()" (when Swift) + # or identifier: "TestThisDude/testFailureJosh2" (when Objective-C) + if self.test_case_name.start_with?("-[") && self.test_case_name.end_with?("]") + return self.test_case_name[2...-1].tr(" ", "/") + end + return self.test_case_name.tr(".", "/") + end + def failure_message new_message = self.message if self.document_location_in_creating_workspace&.url diff --git a/trainer/spec/fixtures/Test.objc.xcresult/Data/data.0~QcTkA55UPcxEP1nO1AY1osK3wJ6ccJbYiM6K7BJmWZ0MFG5UOgWiKPIxZQdQeP-BtGoBEwiEcoYSkz_QqfjjMA== b/trainer/spec/fixtures/Test.objc.xcresult/Data/data.0~QcTkA55UPcxEP1nO1AY1osK3wJ6ccJbYiM6K7BJmWZ0MFG5UOgWiKPIxZQdQeP-BtGoBEwiEcoYSkz_QqfjjMA== new file mode 100644 index 00000000000..bde6eb37acb Binary files /dev/null and b/trainer/spec/fixtures/Test.objc.xcresult/Data/data.0~QcTkA55UPcxEP1nO1AY1osK3wJ6ccJbYiM6K7BJmWZ0MFG5UOgWiKPIxZQdQeP-BtGoBEwiEcoYSkz_QqfjjMA== differ diff --git a/trainer/spec/fixtures/Test.objc.xcresult/Data/data.0~X7J2zgrHmeOeXrqjN4i9NpJunCOzuFwvG8Jap1VZxvIbhWezMh3vFXEmz1umKNEzvzPaQgZfSqBlgcgIowxQdg== b/trainer/spec/fixtures/Test.objc.xcresult/Data/data.0~X7J2zgrHmeOeXrqjN4i9NpJunCOzuFwvG8Jap1VZxvIbhWezMh3vFXEmz1umKNEzvzPaQgZfSqBlgcgIowxQdg== new file mode 100644 index 00000000000..cf1d9746cc1 Binary files /dev/null and b/trainer/spec/fixtures/Test.objc.xcresult/Data/data.0~X7J2zgrHmeOeXrqjN4i9NpJunCOzuFwvG8Jap1VZxvIbhWezMh3vFXEmz1umKNEzvzPaQgZfSqBlgcgIowxQdg== differ diff --git a/trainer/spec/fixtures/Test.objc.xcresult/Data/refs.0~QcTkA55UPcxEP1nO1AY1osK3wJ6ccJbYiM6K7BJmWZ0MFG5UOgWiKPIxZQdQeP-BtGoBEwiEcoYSkz_QqfjjMA== b/trainer/spec/fixtures/Test.objc.xcresult/Data/refs.0~QcTkA55UPcxEP1nO1AY1osK3wJ6ccJbYiM6K7BJmWZ0MFG5UOgWiKPIxZQdQeP-BtGoBEwiEcoYSkz_QqfjjMA== new file mode 100644 index 00000000000..5a4fc51debe Binary files /dev/null and b/trainer/spec/fixtures/Test.objc.xcresult/Data/refs.0~QcTkA55UPcxEP1nO1AY1osK3wJ6ccJbYiM6K7BJmWZ0MFG5UOgWiKPIxZQdQeP-BtGoBEwiEcoYSkz_QqfjjMA== differ diff --git a/trainer/spec/fixtures/Test.objc.xcresult/Data/refs.0~X7J2zgrHmeOeXrqjN4i9NpJunCOzuFwvG8Jap1VZxvIbhWezMh3vFXEmz1umKNEzvzPaQgZfSqBlgcgIowxQdg== b/trainer/spec/fixtures/Test.objc.xcresult/Data/refs.0~X7J2zgrHmeOeXrqjN4i9NpJunCOzuFwvG8Jap1VZxvIbhWezMh3vFXEmz1umKNEzvzPaQgZfSqBlgcgIowxQdg== new file mode 100644 index 00000000000..180c917bb4b Binary files /dev/null and b/trainer/spec/fixtures/Test.objc.xcresult/Data/refs.0~X7J2zgrHmeOeXrqjN4i9NpJunCOzuFwvG8Jap1VZxvIbhWezMh3vFXEmz1umKNEzvzPaQgZfSqBlgcgIowxQdg== differ diff --git a/trainer/spec/fixtures/Test.objc.xcresult/Info.plist b/trainer/spec/fixtures/Test.objc.xcresult/Info.plist new file mode 100644 index 00000000000..96e66c86ece --- /dev/null +++ b/trainer/spec/fixtures/Test.objc.xcresult/Info.plist @@ -0,0 +1,29 @@ + + + + + dateCreated + 2024-04-23T23:38:03Z + externalLocations + + rootId + + hash + 0~QcTkA55UPcxEP1nO1AY1osK3wJ6ccJbYiM6K7BJmWZ0MFG5UOgWiKPIxZQdQeP-BtGoBEwiEcoYSkz_QqfjjMA== + + storage + + backend + fileBacked2 + compression + standard + + version + + major + 3 + minor + 39 + + + diff --git a/trainer/spec/test_parser_spec.rb b/trainer/spec/test_parser_spec.rb index af977270a72..130a3ed92b8 100644 --- a/trainer/spec/test_parser_spec.rb +++ b/trainer/spec/test_parser_spec.rb @@ -245,6 +245,53 @@ } ]) end + + it "works as expected with Objective C xcresult", requires_xcode: true do + tp = Trainer::TestParser.new("./trainer/spec/fixtures/Test.objc.xcresult") + expect(tp.data).to eq([ + { + project_path: "HelloWorldTest.xcodeproj", + target_name: "HelloWorldTestTests", + test_name: "HelloWorldTestTests", + configuration_name: "Test Scheme Action", + duration: 0.04512190818786621, + tests: [ + { + identifier: "HelloWorldTestTests.testExample", + name: "testExample", + duration: 0.0011409521102905273, + status: "Success", + test_group: "HelloWorldTestTests", + guid: "", + }, + { + identifier: "HelloWorldTestTests.testFailure", + name: "testFailure", + duration: 0.043980956077575684, + status: "Failure", + test_group: "HelloWorldTestTests", + guid: "", + failures: [ + { + failure_message: "((NO) is true) failed - Fail (/Users/jsoffian/HelloWorldTest/HelloWorldTestTests/HelloWorldTestTests.m#CharacterRangeLen=0&EndingLineNumber=39&StartingLineNumber=39)", + file_name: "", + line_number: 0, + message: "", + performance_failure: {} + } + ] + } + ], + number_of_tests: 2, + number_of_failures: 1, + number_of_skipped: 0, + number_of_tests_excluding_retries: 2, + number_of_failures_excluding_retries: 1, + number_of_retries: 0 + } + ]) + end + end end end