Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions Sources/xcresultparser/JunitXML.swift
Original file line number Diff line number Diff line change
Expand Up @@ -293,10 +293,13 @@ public struct JunitXML: XmlSerializable {
nodeNames: nodeNames
)
if test.isFailed {
if let summary = test.failureSummary(in: failureSummaries) {
testcase.addChild(summary.failureXML(projectRoot: projectRoot))
} else {
let summaries = test.failureSummaries(in: failureSummaries)
if summaries.isEmpty {
testcase.addChild(failureWithoutSummary)
} else {
for summary in summaries {
testcase.addChild(summary.failureXML(projectRoot: projectRoot))
}
}
} else if test.isSkipped {
testcase.addChild(skippedWithoutSummary)
Expand All @@ -321,7 +324,7 @@ extension XMLElement {
}
}

private extension ActionTestMetadata {
extension ActionTestMetadata {
func xmlNode(
classname: String,
numFormatter: NumberFormatter,
Expand All @@ -348,8 +351,8 @@ private extension ActionTestMetadata {
return testcase
}

func failureSummary(in summaries: [TestFailureIssueSummary]) -> TestFailureIssueSummary? {
return summaries.first { summary in
func failureSummaries(in summaries: [TestFailureIssueSummary]) -> [TestFailureIssueSummary] {
return summaries.filter { summary in
return summary.testCaseName == identifier?.replacingOccurrences(of: "/", with: ".") ||
summary.testCaseName == "-[\(identifier?.replacingOccurrences(of: "/", with: " ") ?? "")]"
}
Expand Down
98 changes: 98 additions & 0 deletions Tests/XcresultparserTests/XcresultparserTests.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Foundation
@testable import XcresultparserLib
import XCResultKit
import Testing

@MainActor
Expand Down Expand Up @@ -499,6 +500,73 @@ struct XcresultparserTests {
try assertXmlTestReportsAreEqual(expectedFileName: "junit_repeated", actual: junitXML)
}

@Test
func testFailureSummariesReturnsAllMatchingFailures() throws {
let testMetadata = try makeTestMetadata()

let matchingFailure1 = try makeFailureSummary(
testCaseName: "TestClass.testMethod",
message: "First assertion failed"
)
let matchingFailure2 = try makeFailureSummary(
testCaseName: "TestClass.testMethod",
message: "Second assertion failed"
)
let nonMatchingFailure = try makeFailureSummary(
testCaseName: "OtherClass.otherMethod",
message: "Unrelated failure"
)

let result = testMetadata.failureSummaries(in: [matchingFailure1, nonMatchingFailure, matchingFailure2])

#expect(result.count == 2)
#expect(result[0].message == "First assertion failed")
#expect(result[1].message == "Second assertion failed")
}

@Test
func testFailureSummariesWithBracketNotation() throws {
let testMetadata = try makeTestMetadata()

// Objective-C bracket notation: -[TestClass testMethod]
let bracketFailure1 = try makeFailureSummary(
testCaseName: "-[TestClass testMethod]",
message: "Bracket notation failure 1"
)
let bracketFailure2 = try makeFailureSummary(
testCaseName: "-[TestClass testMethod]",
message: "Bracket notation failure 2"
)

let result = testMetadata.failureSummaries(in: [bracketFailure1, bracketFailure2])

#expect(result.count == 2)
#expect(result[0].message == "Bracket notation failure 1")
#expect(result[1].message == "Bracket notation failure 2")
}

@Test
func testFailureSummariesReturnsEmptyForNoMatches() throws {
let testMetadata = try makeTestMetadata()
let nonMatchingFailure = try makeFailureSummary(
testCaseName: "OtherClass.otherMethod",
message: "Unrelated failure"
)

let result = testMetadata.failureSummaries(in: [nonMatchingFailure])

#expect(result.isEmpty)
}

@Test
func testFailureSummariesWithEmptyArray() throws {
let testMetadata = try makeTestMetadata()

let result = testMetadata.failureSummaries(in: [])

#expect(result.isEmpty)
}

@Test
func testCleanCodeWarnings() throws {
let xcresultFile = Bundle.module.url(forResource: "test", withExtension: "xcresult")!
Expand Down Expand Up @@ -650,6 +718,36 @@ struct XcresultparserTests {

// MARK: helper functions

private func makeTestMetadata(
identifier: String = "TestClass/testMethod",
name: String = "testMethod",
status: String = "Failure",
duration: String = "0.5"
) throws -> ActionTestMetadata {
let json: [String: AnyObject] = [
"_type": ["_name": "ActionTestMetadata"] as AnyObject,
"identifier": ["_type": ["_name": "String"], "_value": identifier] as AnyObject,
"name": ["_type": ["_name": "String"], "_value": name] as AnyObject,
"testStatus": ["_type": ["_name": "String"], "_value": status] as AnyObject,
"duration": ["_type": ["_name": "Double"], "_value": duration] as AnyObject
]
return try #require(ActionTestMetadata(json))
}

private func makeFailureSummary(
testCaseName: String,
message: String = "Assertion failed",
issueType: String = "Assertion Failure"
) throws -> TestFailureIssueSummary {
let json: [String: AnyObject] = [
"_type": ["_name": "TestFailureIssueSummary"] as AnyObject,
"testCaseName": ["_type": ["_name": "String"], "_value": testCaseName] as AnyObject,
"issueType": ["_type": ["_name": "String"], "_value": issueType] as AnyObject,
"message": ["_type": ["_name": "String"], "_value": message] as AnyObject
]
return try #require(TestFailureIssueSummary(json))
}

func assertXmlTestReportsAreEqual(
expectedFileName: String,
actual: XmlSerializable,
Expand Down