Skip to content

Commit

Permalink
Include minimal details about skipped test in output.
Browse files Browse the repository at this point in the history
As per Jenkins/JUnit xml docs in https://llg.cubic.org/docs/junit/
  • Loading branch information
aufflick committed Feb 17, 2022
1 parent 742d6f5 commit 1e0f625
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 13 deletions.
25 changes: 21 additions & 4 deletions Sources/SwiftTestReporter/Models.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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] {
Expand All @@ -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 {
Expand All @@ -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)
}
}

Expand Down
13 changes: 8 additions & 5 deletions Sources/SwiftTestReporter/Reporters/JUnit/JUnitElement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -22,22 +22,25 @@ indirect enum JUnitElement: CustomStringConvertible {
case .testSuitesEnd:
return "</testsuites>"

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<testsuite tests=\"\(testsCount)\" failures=\"\(failuresCount)\" disabled=\"\(disabledCount)\" errors=\"\(errorsCount)\" time=\"\(time)\" name=\"\(name)\">
\t<testsuite tests=\"\(testsCount)\" failures=\"\(failuresCount)\" disabled=\"\(disabledCount)\" errors=\"\(errorsCount)\" skipped=\"\(skippedCount)\" time=\"\(time)\" name=\"\(name)\">
\(testsElement)
\t</testsuite>
"""

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<testcase classname=\"\(className)\" name=\"\(name)\" time=\"\(duration)\">"
if let failure = failure {
testCaseElement += failure.description
}
if let error = error {
testCaseElement += error.description
}
if skipped {
testCaseElement += "<skipped/>"
}
testCaseElement += "</testcase>"
return testCaseElement

Expand Down
4 changes: 3 additions & 1 deletion Sources/SwiftTestReporter/Reporters/JUnit/Models+JUnit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ extension TestSuite: XMLJUnitFormat {
failuresCount: testCasesWithFailure.count,
disabledCount: 0,
errorsCountInt: testCasesWithError.count,
skippedCount: skippedTestCount,
duration: duration,
name: name,
tests: testCases
Expand All @@ -24,7 +25,8 @@ extension Test: XMLJUnitFormat {
name: name,
duration: duration,
failure: failure?.getXMLElement(),
error: error?.getXMLElement()
error: error?.getXMLElement(),
skipped: skipped
)
}
}
Expand Down
3 changes: 3 additions & 0 deletions Sources/SwiftTestReporter/TestObserver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand Down
30 changes: 27 additions & 3 deletions Tests/SwiftTestReporterTests/JUnitReporterTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class JUnitReporterTests: XCTestCase {
let expected = """
<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
<testsuite tests="0" failures="0" disabled="0" errors="0" time="0.0" name="Stub Test">
<testsuite tests="0" failures="0" disabled="0" errors="0" skipped="0" time="0.0" name="Stub Test">
</testsuite>
</testsuites>
Expand All @@ -40,7 +40,7 @@ class JUnitReporterTests: XCTestCase {
let expected = """
<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
<testsuite tests="1" failures="1" disabled="0" errors="0" time="0.0" name="TestFoo">
<testsuite tests="1" failures="1" disabled="0" errors="0" skipped="0" time="0.0" name="TestFoo">
<testcase classname="\(className)" name="\(testName)" time="0.0">
<failure message="test failed"></failure>
</testcase>
Expand All @@ -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 = """
<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
<testsuite tests="1" failures="0" disabled="0" errors="0" skipped="1" time="0.0" name="TestFoo">
<testcase classname="\(className)" name="\(testName)" time="0.0"><skipped/></testcase>
</testsuite>
</testsuites>
"""
JUnitReporter().report(for: [testSuite]) { content in
XCTAssertEqual(content.replacingTabsWithSpaces(), expected.replacingTabsWithSpaces())
}
}


func testProperEscapingOfErrorMessages() {
#if os(Linux)
Expand All @@ -65,7 +89,7 @@ class JUnitReporterTests: XCTestCase {
let expected = """
<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
<testsuite tests="1" failures="1" disabled="0" errors="0" time="0.0" name="TestFoo">
<testsuite tests="1" failures="1" disabled="0" errors="0" skipped="0" time="0.0" name="TestFoo">
<testcase classname="\(className)" name="\(testName)" time="0.0">
<failure message="&#34;test&#34; &#34;failed&#34;"></failure>
</testcase>
Expand Down

0 comments on commit 1e0f625

Please sign in to comment.