Skip to content

Commit 61ddd74

Browse files
committed
Adjust duration output from the summary output lines
Instead of outputting the average and summed execution time for each test run, output the summed execution time of each test run and the total elapsed time between the beginning and end of the test case's execution. The new output follows the behavior of Darwin's XCTest framework.
1 parent 75d601c commit 61ddd74

File tree

3 files changed

+53
-42
lines changed

3 files changed

+53
-42
lines changed

XCTest/XCTestCase.swift

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -31,38 +31,37 @@ extension XCTestCase {
3131
var totalDuration = 0.0
3232
var totalFailures = 0
3333
var unexpectedFailures = 0
34-
for (name, test) in tests {
35-
XCTCurrentTestCase = self
36-
let method = "\(self.dynamicType).\(name)"
37-
var duration: Double = 0.0
38-
print("Test Case '\(method)' started.")
39-
40-
setUp()
41-
42-
let start = currentTimeIntervalSinceReferenceTime()
43-
test()
44-
let end = currentTimeIntervalSinceReferenceTime()
45-
46-
tearDown()
47-
48-
duration = end - start
49-
totalDuration += duration
50-
for failure in XCTCurrentFailures {
51-
failure.emit(method)
52-
totalFailures += 1
53-
if !failure.expected {
54-
unexpectedFailures += 1
34+
let overallDuration = measureTimeExecutingBlock {
35+
for (name, test) in tests {
36+
XCTCurrentTestCase = self
37+
let method = "\(self.dynamicType).\(name)"
38+
print("Test Case '\(method)' started.")
39+
40+
setUp()
41+
42+
let duration = measureTimeExecutingBlock(test)
43+
44+
tearDown()
45+
46+
totalDuration += duration
47+
for failure in XCTCurrentFailures {
48+
failure.emit(method)
49+
totalFailures += 1
50+
if !failure.expected {
51+
unexpectedFailures += 1
52+
}
5553
}
54+
var result = "passed"
55+
if XCTCurrentFailures.count > 0 {
56+
result = "failed"
57+
}
58+
print("Test Case '\(method)' \(result) (\(printableStringForTimeInterval(duration)) seconds).")
59+
XCTAllRuns.append(XCTRun(duration: duration, method: method, passed: XCTCurrentFailures.count == 0, failures: XCTCurrentFailures))
60+
XCTCurrentFailures.removeAll()
61+
XCTCurrentTestCase = nil
5662
}
57-
var result = "passed"
58-
if XCTCurrentFailures.count > 0 {
59-
result = "failed"
60-
}
61-
print("Test Case '\(method)' \(result) (\(printableStringForTimeInterval(duration)) seconds).")
62-
XCTAllRuns.append(XCTRun(duration: duration, method: method, passed: XCTCurrentFailures.count == 0, failures: XCTCurrentFailures))
63-
XCTCurrentFailures.removeAll()
64-
XCTCurrentTestCase = nil
6563
}
64+
6665
var testCountSuffix = "s"
6766
if tests.count == 1 {
6867
testCountSuffix = ""
@@ -71,9 +70,8 @@ extension XCTestCase {
7170
if totalFailures == 1 {
7271
failureSuffix = ""
7372
}
74-
let averageDuration = totalDuration / Double(tests.count)
75-
76-
print("Executed \(tests.count) test\(testCountSuffix), with \(totalFailures) failure\(failureSuffix) (\(unexpectedFailures) unexpected) in \(printableStringForTimeInterval(averageDuration)) (\(printableStringForTimeInterval(totalDuration))) seconds")
73+
74+
print("Executed \(tests.count) test\(testCountSuffix), with \(totalFailures) failure\(failureSuffix) (\(unexpectedFailures) unexpected) in \(printableStringForTimeInterval(totalDuration)) (\(printableStringForTimeInterval(overallDuration))) seconds")
7775
}
7876

7977
// This function is for the use of XCTestCase only, but we must make it public or clients will get a link failure when using XCTest (23476006)

XCTest/XCTestMain.swift

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ struct XCTFailure {
3030
}
3131

3232
internal struct XCTRun {
33-
var duration: Double
33+
var duration: TimeInterval
3434
var method: String
3535
var passed: Bool
3636
var failures: [XCTFailure]
@@ -44,9 +44,12 @@ internal struct XCTRun {
4444
/// This function will not return. If the test cases pass, then it will call `exit(0)`. If there is a failure, then it will call `exit(1)`.
4545
/// - Parameter testCases: An array of test cases to run.
4646
@noreturn public func XCTMain(testCases: [XCTestCase]) {
47-
for testCase in testCases {
48-
testCase.invokeTest()
47+
let overallDuration = measureTimeExecutingBlock {
48+
for testCase in testCases {
49+
testCase.invokeTest()
50+
}
4951
}
52+
5053
let (totalDuration, totalFailures, totalUnexpectedFailures) = XCTAllRuns.reduce((0.0, 0, 0)) { totals, run in (totals.0 + run.duration, totals.1 + run.failures.count, totals.2 + run.unexpectedFailures.count) }
5154

5255
var testCountSuffix = "s"
@@ -57,8 +60,8 @@ internal struct XCTRun {
5760
if totalFailures == 1 {
5861
failureSuffix = ""
5962
}
60-
let averageDuration = totalDuration / Double(XCTAllRuns.count)
61-
print("Total executed \(XCTAllRuns.count) test\(testCountSuffix), with \(totalFailures) failure\(failureSuffix) (\(totalUnexpectedFailures) unexpected) in \(printableStringForTimeInterval(averageDuration)) (\(printableStringForTimeInterval(totalDuration))) seconds")
63+
64+
print("Total executed \(XCTAllRuns.count) test\(testCountSuffix), with \(totalFailures) failure\(failureSuffix) (\(totalUnexpectedFailures) unexpected) in \(printableStringForTimeInterval(totalDuration)) (\(printableStringForTimeInterval(overallDuration))) seconds")
6265
exit(totalFailures > 0 ? 1 : 0)
6366
}
6467

XCTest/XCTimeUtilities.swift

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,28 @@
1717
import Darwin
1818
#endif
1919

20+
internal typealias TimeInterval = Double
21+
2022
/// Returns the number of seconds since the reference time as a Double.
21-
internal func currentTimeIntervalSinceReferenceTime() -> Double {
23+
private func currentTimeIntervalSinceReferenceTime() -> TimeInterval {
2224
var tv = timeval()
23-
let currentTime = withUnsafeMutablePointer(&tv, { (t: UnsafeMutablePointer<timeval>) -> Double in
25+
let currentTime = withUnsafeMutablePointer(&tv, { (t: UnsafeMutablePointer<timeval>) -> TimeInterval in
2426
gettimeofday(t, nil)
25-
return Double(t.memory.tv_sec) + Double(t.memory.tv_usec) / 1000000.0
27+
return TimeInterval(t.memory.tv_sec) + TimeInterval(t.memory.tv_usec) / 1000000.0
2628
})
2729
return currentTime
2830
}
2931

32+
/// Execute the given block and return the time spent during execution
33+
internal func measureTimeExecutingBlock(@noescape block: () -> Void) -> TimeInterval {
34+
let start = currentTimeIntervalSinceReferenceTime()
35+
block()
36+
let end = currentTimeIntervalSinceReferenceTime()
37+
38+
return end - start
39+
}
40+
3041
/// Returns a string version of the given time interval rounded to no more than 3 decimal places.
31-
internal func printableStringForTimeInterval(timeInterval: Double) -> String {
42+
internal func printableStringForTimeInterval(timeInterval: TimeInterval) -> String {
3243
return String(round(timeInterval * 1000.0) / 1000.0)
3344
}
34-

0 commit comments

Comments
 (0)