Skip to content

Commit 22e1c07

Browse files
committed
[SR-5643] Add XCTPeformanceMetric string enum.
In Xcode 9, the XCTPerformanceMetric_WallClockTime string constant was turned into a string enumeration to improve the ability to use strong typing at call sites using it. At the same time, the defaultPerformanceMetrics class function on XCTestCase was changed to be a class property.
1 parent f2d129a commit 22e1c07

File tree

3 files changed

+41
-19
lines changed

3 files changed

+41
-19
lines changed

Sources/XCTest/Public/XCTestCase+Performance.swift

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,30 @@
1111
// Methods on XCTestCase for testing the performance of code blocks.
1212
//
1313

14-
/// Records wall clock time in seconds between `startMeasuring`/`stopMeasuring`.
15-
public let XCTPerformanceMetric_WallClockTime = WallClockTimeMetric.name
14+
public struct XCTPerformanceMetric : RawRepresentable, Equatable, Hashable {
15+
public private(set) var rawValue: String
16+
17+
public init(_ rawValue: String) {
18+
self.rawValue = rawValue
19+
}
20+
21+
public init(rawValue: String) {
22+
self.rawValue = rawValue
23+
}
24+
25+
public var hashValue: Int {
26+
return rawValue.hashValue
27+
}
28+
29+
public static func ==(_ lhs: XCTPerformanceMetric, _ rhs: XCTPerformanceMetric) -> Bool {
30+
return lhs.rawValue == rhs.rawValue
31+
}
32+
}
33+
34+
public extension XCTPerformanceMetric {
35+
/// Records wall clock time in seconds between `startMeasuring`/`stopMeasuring`.
36+
public static let wallClockTime = XCTPerformanceMetric(rawValue: WallClockTimeMetric.name)
37+
}
1638

1739
/// The following methods are called from within a test method to carry out
1840
/// performance testing on blocks of code.
@@ -21,11 +43,11 @@ public extension XCTestCase {
2143
/// The names of the performance metrics to measure when invoking `measure(block:)`.
2244
/// Returns `XCTPerformanceMetric_WallClockTime` by default. Subclasses can
2345
/// override this to change the behavior of `measure(block:)`
24-
class func defaultPerformanceMetrics() -> [String] {
25-
return [XCTPerformanceMetric_WallClockTime]
46+
class var defaultPerformanceMetrics: [XCTPerformanceMetric] {
47+
return [.wallClockTime]
2648
}
2749

28-
/// Call from a test method to measure resources (`defaultPerformanceMetrics()`)
50+
/// Call from a test method to measure resources (`defaultPerformanceMetrics`)
2951
/// used by the block in the current process.
3052
///
3153
/// func testPerformanceOfMyFunction() {
@@ -50,7 +72,7 @@ public extension XCTestCase {
5072
/// ensure compatibility of tests between swift-corelibs-xctest and Apple
5173
/// XCTest, it is not recommended to pass explicit values for `file` and `line`.
5274
func measure(file: StaticString = #file, line: Int = #line, block: () -> Void) {
53-
measureMetrics(type(of: self).defaultPerformanceMetrics(),
75+
measureMetrics(type(of: self).defaultPerformanceMetrics,
5476
automaticallyStartMeasuring: true,
5577
file: file,
5678
line: line,
@@ -66,7 +88,7 @@ public extension XCTestCase {
6688
/// may interfere the API will measure them separately.
6789
///
6890
/// func testMyFunction2_WallClockTime() {
69-
/// measureMetrics(type(of: self).defaultPerformanceMetrics(), automaticallyStartMeasuring: false) {
91+
/// measureMetrics(type(of: self).defaultPerformanceMetrics, automaticallyStartMeasuring: false) {
7092
///
7193
/// // Do setup work that needs to be done for every iteration but
7294
/// // you don't want to measure before the call to `startMeasuring()`
@@ -103,12 +125,12 @@ public extension XCTestCase {
103125
/// these methods are not exactly identical between these environments. To
104126
/// ensure compatibility of tests between swift-corelibs-xctest and Apple
105127
/// XCTest, it is not recommended to pass explicit values for `file` and `line`.
106-
func measureMetrics(_ metrics: [String], automaticallyStartMeasuring: Bool, file: StaticString = #file, line: Int = #line, for block: () -> Void) {
128+
func measureMetrics(_ metrics: [XCTPerformanceMetric], automaticallyStartMeasuring: Bool, file: StaticString = #file, line: Int = #line, for block: () -> Void) {
107129
guard _performanceMeter == nil else {
108130
return recordAPIViolation(description: "Can only record one set of metrics per test method.", file: file, line: line)
109131
}
110132

111-
PerformanceMeter.measureMetrics(metrics, delegate: self, file: file, line: line) { meter in
133+
PerformanceMeter.measureMetrics(metrics.map({ $0.rawValue }), delegate: self, file: file, line: line) { meter in
112134
self._performanceMeter = meter
113135
if automaticallyStartMeasuring {
114136
meter.startMeasuring(file: file, line: line)

Tests/Functional/Performance/Misuse/main.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,20 @@ class PerformanceMisuseTestCase: XCTestCase {
2121
// CHECK: .*/Misuse/main.swift:[[@LINE+1]]: error: PerformanceMisuseTestCase.test_whenMeasuringMultipleInOneTest_fails : API violation - Can only record one set of metrics per test method.
2222
measure {}
2323
// CHECK: .*/Misuse/main.swift:[[@LINE+1]]: error: PerformanceMisuseTestCase.test_whenMeasuringMultipleInOneTest_fails : API violation - Can only record one set of metrics per test method.
24-
measureMetrics([XCTPerformanceMetric_WallClockTime], automaticallyStartMeasuring: true) {}
24+
measureMetrics([.wallClockTime], automaticallyStartMeasuring: true) {}
2525
}
2626
// CHECK: Test Case 'PerformanceMisuseTestCase.test_whenMeasuringMultipleInOneTest_fails' failed \(\d+\.\d+ seconds\)
2727

2828
// CHECK: Test Case 'PerformanceMisuseTestCase.test_whenMeasuringMetricsAndNotStartingOrEnding_fails' started at \d+-\d+-\d+ \d+:\d+:\d+\.\d+
2929
func test_whenMeasuringMetricsAndNotStartingOrEnding_fails() {
3030
// CHECK: .*/Misuse/main.swift:[[@LINE+1]]: error: PerformanceMisuseTestCase.test_whenMeasuringMetricsAndNotStartingOrEnding_fails : API violation - startMeasuring\(\) must be called during the block.
31-
measureMetrics([XCTPerformanceMetric_WallClockTime], automaticallyStartMeasuring: false) {}
31+
measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) {}
3232
}
3333
// CHECK: Test Case 'PerformanceMisuseTestCase.test_whenMeasuringMetricsAndNotStartingOrEnding_fails' failed \(\d+\.\d+ seconds\)
3434

3535
// CHECK: Test Case 'PerformanceMisuseTestCase.test_whenMeasuringMetricsAndStoppingWithoutStarting_fails' started at \d+-\d+-\d+ \d+:\d+:\d+\.\d+
3636
func test_whenMeasuringMetricsAndStoppingWithoutStarting_fails() {
37-
measureMetrics([XCTPerformanceMetric_WallClockTime], automaticallyStartMeasuring: false) {
37+
measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) {
3838
// CHECK: .*/Misuse/main.swift:[[@LINE+1]]: error: PerformanceMisuseTestCase.test_whenMeasuringMetricsAndStoppingWithoutStarting_fails : API violation - Cannot stop measuring before starting measuring.
3939
self.stopMeasuring()
4040
}
@@ -43,7 +43,7 @@ class PerformanceMisuseTestCase: XCTestCase {
4343

4444
// CHECK: Test Case 'PerformanceMisuseTestCase.test_whenMeasuringMetricsAndStartingTwice_fails' started at \d+-\d+-\d+ \d+:\d+:\d+\.\d+
4545
func test_whenMeasuringMetricsAndStartingTwice_fails() {
46-
measureMetrics([XCTPerformanceMetric_WallClockTime], automaticallyStartMeasuring: false) {
46+
measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) {
4747
self.startMeasuring()
4848
// CHECK: .*/Misuse/main.swift:[[@LINE+1]]: error: PerformanceMisuseTestCase.test_whenMeasuringMetricsAndStartingTwice_fails : API violation - Already called startMeasuring\(\) once this iteration.
4949
self.startMeasuring()
@@ -53,7 +53,7 @@ class PerformanceMisuseTestCase: XCTestCase {
5353

5454
// CHECK: Test Case 'PerformanceMisuseTestCase.test_whenMeasuringMetricsAndStoppingTwice_fails' started at \d+-\d+-\d+ \d+:\d+:\d+\.\d+
5555
func test_whenMeasuringMetricsAndStoppingTwice_fails() {
56-
measureMetrics([XCTPerformanceMetric_WallClockTime], automaticallyStartMeasuring: false) {
56+
measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) {
5757
self.startMeasuring()
5858
self.stopMeasuring()
5959
// CHECK: .*/Misuse/main.swift:[[@LINE+1]]: error: PerformanceMisuseTestCase.test_whenMeasuringMetricsAndStoppingTwice_fails : API violation - Already called stopMeasuring\(\) once this iteration.
@@ -104,7 +104,7 @@ class PerformanceMisuseTestCase: XCTestCase {
104104
// CHECK: Test Case 'PerformanceMisuseTestCase.test_measuringUnknownMetric_fails' started at \d+-\d+-\d+ \d+:\d+:\d+\.\d+
105105
func test_measuringUnknownMetric_fails() {
106106
// CHECK: .*/Misuse/main.swift:[[@LINE+1]]: error: PerformanceMisuseTestCase.test_measuringUnknownMetric_fails : API violation - Unknown metric: UnladenAirspeedVelocity
107-
measureMetrics(["UnladenAirspeedVelocity"], automaticallyStartMeasuring: true) {}
107+
measureMetrics([XCTPerformanceMetric("UnladenAirspeedVelocity")], automaticallyStartMeasuring: true) {}
108108
}
109109
// CHECK: Test Case 'PerformanceMisuseTestCase.test_measuringUnknownMetric_fails' failed \(\d+\.\d+ seconds\)
110110

Tests/Functional/Performance/main.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class PerformanceTestCase: XCTestCase {
3030
// CHECK: Test Case 'PerformanceTestCase.test_measuresMetricsWithAutomaticStartAndStop' passed \(\d+\.\d+ seconds\)
3131
func test_measuresMetricsWithAutomaticStartAndStop() {
3232
var iterationCount = 0
33-
measureMetrics([XCTPerformanceMetric_WallClockTime], automaticallyStartMeasuring: true, for: {
33+
measureMetrics([.wallClockTime], automaticallyStartMeasuring: true, for: {
3434
iterationCount += 1
3535
})
3636
XCTAssertEqual(iterationCount, 10)
@@ -40,7 +40,7 @@ class PerformanceTestCase: XCTestCase {
4040
// CHECK: .*/Performance/main.swift:[[@LINE+3]]: Test Case 'PerformanceTestCase.test_measuresMetricsWithManualStartAndStop' measured \[Time, seconds\] .*
4141
// CHECK: Test Case 'PerformanceTestCase.test_measuresMetricsWithManualStartAndStop' passed \(\d+\.\d+ seconds\)
4242
func test_measuresMetricsWithManualStartAndStop() {
43-
measureMetrics([XCTPerformanceMetric_WallClockTime], automaticallyStartMeasuring: false) {
43+
measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) {
4444
self.startMeasuring()
4545
self.stopMeasuring()
4646
}
@@ -50,15 +50,15 @@ class PerformanceTestCase: XCTestCase {
5050
// CHECK: .*/Performance/main.swift:[[@LINE+3]]: Test Case 'PerformanceTestCase.test_measuresMetricsWithoutExplicitStop' measured \[Time, seconds\] .*
5151
// CHECK: Test Case 'PerformanceTestCase.test_measuresMetricsWithoutExplicitStop' passed \(\d+\.\d+ seconds\)
5252
func test_measuresMetricsWithoutExplicitStop() {
53-
measureMetrics([XCTPerformanceMetric_WallClockTime], automaticallyStartMeasuring: false) {
53+
measureMetrics([.wallClockTime], automaticallyStartMeasuring: false) {
5454
self.startMeasuring()
5555
}
5656
}
5757

5858
// CHECK: Test Case 'PerformanceTestCase.test_hasWallClockAsDefaultPerformanceMetric' started at \d+-\d+-\d+ \d+:\d+:\d+\.\d+
5959
// CHECK: Test Case 'PerformanceTestCase.test_hasWallClockAsDefaultPerformanceMetric' passed \(\d+\.\d+ seconds\)
6060
func test_hasWallClockAsDefaultPerformanceMetric() {
61-
XCTAssertEqual(PerformanceTestCase.defaultPerformanceMetrics(), [XCTPerformanceMetric_WallClockTime])
61+
XCTAssertEqual(PerformanceTestCase.defaultPerformanceMetrics, [.wallClockTime])
6262
}
6363

6464
// CHECK: Test Case 'PerformanceTestCase.test_printsValuesAfterMeasuring' started at \d+-\d+-\d+ \d+:\d+:\d+\.\d+

0 commit comments

Comments
 (0)