diff --git a/Sources/SwiftTestReporter/Models.swift b/Sources/SwiftTestReporter/Models.swift index 7d0dde2..8d30b7b 100644 --- a/Sources/SwiftTestReporter/Models.swift +++ b/Sources/SwiftTestReporter/Models.swift @@ -33,6 +33,10 @@ public final class TestSuite { return Array(testCases.filter { _, value in value.error != nil }.values) } + var skippedTestCount: Int { + return testCases.filter { _, value in value.skipped }.count + } + // MARK: - Helpers static func getTestCaseKey(for testCase: XCTest) -> TestCaseKey { @@ -53,6 +57,13 @@ public final class TestSuite { } } + func markTestSkipped(_ test: XCTest) { + let key = TestSuite.getTestCaseKey(for: test) + if let testCase = testCases[key] { + testCases[key] = testCase.setSkipped() + } + } + func updateTestDuration(for test: XCTest, _ duration: TimeInterval) { let key = TestSuite.getTestCaseKey(for: test) if let testCase = testCases[key] { @@ -75,11 +86,13 @@ public struct Test { let duration: TimeInterval let failure: Failure? let error: Error? + let skipped: Bool - init(_ test: XCTest, failure: Failure? = nil, error: Error? = nil, duration: TimeInterval? = nil) { + init(_ test: XCTest, failure: Failure? = nil, error: Error? = nil, skipped: Bool = false, duration: TimeInterval? = nil) { self.test = test self.failure = failure self.error = error + self.skipped = skipped if let duration = duration { self.duration = duration } else { @@ -91,15 +104,19 @@ public struct Test { // Make struct immutable extension Test { func setFailure(_ failure: Failure) -> Test { - return Test(test, failure: failure, error: error, duration: duration) + return Test(test, failure: failure, error: error, skipped: skipped, duration: duration) } func setError(_ error: Error) -> Test { - return Test(test, failure: failure, error: error, duration: duration) + return Test(test, failure: failure, error: error, skipped: skipped, duration: duration) } func setDuration(_ duration: TimeInterval) -> Test { - return Test(test, failure: failure, error: error, duration: duration) + return Test(test, failure: failure, error: error, skipped: skipped, duration: duration) + } + + func setSkipped() -> Test { + return Test(test, failure: failure, error: error, skipped: true, duration: duration) } } diff --git a/Sources/SwiftTestReporter/Reporters/JUnit/JUnitElement.swift b/Sources/SwiftTestReporter/Reporters/JUnit/JUnitElement.swift index bb78891..abb1595 100644 --- a/Sources/SwiftTestReporter/Reporters/JUnit/JUnitElement.swift +++ b/Sources/SwiftTestReporter/Reporters/JUnit/JUnitElement.swift @@ -6,8 +6,8 @@ indirect enum JUnitElement: CustomStringConvertible { case preamble case testSuitesStart case testSuitesEnd - case testSuite(testsCount: Int, failuresCount: Int, disabledCount: Int, errorsCountInt: Int, duration: TimeInterval, name: String, tests: [JUnitElement]) - case testCase(className: String, name: String, duration: TimeInterval, failure: JUnitElement?, error: JUnitElement?) + case testSuite(testsCount: Int, failuresCount: Int, disabledCount: Int, errorsCountInt: Int, skippedCount: Int, duration: TimeInterval, name: String, tests: [JUnitElement]) + case testCase(className: String, name: String, duration: TimeInterval, failure: JUnitElement?, error: JUnitElement?, skipped: Bool) case failure(message: String) case error(message: String) @@ -22,15 +22,15 @@ indirect enum JUnitElement: CustomStringConvertible { case .testSuitesEnd: return "" - case .testSuite(let testsCount, let failuresCount, let disabledCount, let errorsCount, let time, let name, let tests): + case .testSuite(let testsCount, let failuresCount, let disabledCount, let errorsCount, let skippedCount, let time, let name, let tests): let testsElement = tests.map { $0.description }.joined(separator: "\n") return """ - \t + \t \(testsElement) \t """ - case .testCase(let className, let name, let duration, let failure, let error): + case .testCase(let className, let name, let duration, let failure, let error, let skipped): var testCaseElement = "\t\t" if let failure = failure { testCaseElement += failure.description @@ -38,6 +38,9 @@ indirect enum JUnitElement: CustomStringConvertible { if let error = error { testCaseElement += error.description } + if skipped { + testCaseElement += "" + } testCaseElement += "" return testCaseElement diff --git a/Sources/SwiftTestReporter/Reporters/JUnit/Models+JUnit.swift b/Sources/SwiftTestReporter/Reporters/JUnit/Models+JUnit.swift index 205eee1..fee72bb 100644 --- a/Sources/SwiftTestReporter/Reporters/JUnit/Models+JUnit.swift +++ b/Sources/SwiftTestReporter/Reporters/JUnit/Models+JUnit.swift @@ -10,6 +10,7 @@ extension TestSuite: XMLJUnitFormat { failuresCount: testCasesWithFailure.count, disabledCount: 0, errorsCountInt: testCasesWithError.count, + skippedCount: skippedTestCount, duration: duration, name: name, tests: testCases @@ -24,7 +25,8 @@ extension Test: XMLJUnitFormat { name: name, duration: duration, failure: failure?.getXMLElement(), - error: error?.getXMLElement() + error: error?.getXMLElement(), + skipped: skipped ) } } diff --git a/Sources/SwiftTestReporter/TestObserver.swift b/Sources/SwiftTestReporter/TestObserver.swift index cc048e2..1deac9e 100644 --- a/Sources/SwiftTestReporter/TestObserver.swift +++ b/Sources/SwiftTestReporter/TestObserver.swift @@ -43,6 +43,9 @@ extension TestObserver: XCTestObservation { public func testCaseDidFinish(_ testCase: XCTestCase) { let testRun = testCase.testRun! if let currentTestSuite = currentTestSuite { + if testRun.hasBeenSkipped { + currentTestSuite.markTestSkipped(testCase) + } currentTestSuite.updateTestDuration(for: testCase, testRun.totalDuration) } } diff --git a/Tests/SwiftTestReporterTests/JUnitReporterTests.swift b/Tests/SwiftTestReporterTests/JUnitReporterTests.swift index e28cc5e..c0f62b6 100644 --- a/Tests/SwiftTestReporterTests/JUnitReporterTests.swift +++ b/Tests/SwiftTestReporterTests/JUnitReporterTests.swift @@ -17,7 +17,7 @@ class JUnitReporterTests: XCTestCase { let expected = """ - + @@ -40,7 +40,7 @@ class JUnitReporterTests: XCTestCase { let expected = """ - + @@ -51,6 +51,30 @@ class JUnitReporterTests: XCTestCase { XCTAssertEqual(content.replacingTabsWithSpaces(), expected.replacingTabsWithSpaces()) } } + + func testReporterShouldReturnXMLForSkippedTest() { + #if os(Linux) + let className = "SwiftTestReporterTests.JUnitReporterTests" + let testName = "testReporterShouldReturnXMLForSkippedTest" + #else + let className = "-[JUnitReporterTests testReporterShouldReturnXMLForSkippedTest]" + let testName = "-[JUnitReporterTests testReporterShouldReturnXMLForSkippedTest]" + #endif + let testCase = Test(self).setSkipped() + let testSuite = makeTestCaseStub(name: "TestFoo", testCases: ["test": testCase]) + let expected = """ + + + + + + + """ + JUnitReporter().report(for: [testSuite]) { content in + XCTAssertEqual(content.replacingTabsWithSpaces(), expected.replacingTabsWithSpaces()) + } + } + func testProperEscapingOfErrorMessages() { #if os(Linux) @@ -65,7 +89,7 @@ class JUnitReporterTests: XCTestCase { let expected = """ - +