Skip to content

[SR-5643] Adopt Swift 4 API adjustments from Apple XCTest #198

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 21, 2017

Conversation

briancroom
Copy link
Contributor

In Xcode 9, XCTest underwent a bit of a "Swiftification" effort to adopt more modern Swift idioms and improve how its APIs get presented in Swift 4. This PR adopts those changes here as well. They include:

  • Migrate from UInt -> Int. Prior to Swift 4, several XCTest APIs were brought into Swift using the
    UInt type, in contrast to other Apple system frameworks which consistently used Int. In Swift 4, XCTest began being treated as a system framework and now uses Int as well.
  • Make XCTestObservationCenter.shared a class property instead of class function.
  • Add an XCTestError struct. This is to match the struct generated by the Objective-C importer for
    Apple XCTest due to its XCTestErrorCode having been marked with the NSErrorDomain API note.
  • Add XCTPerformanceMetric 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.

@briancroom
Copy link
Contributor Author

@swift-ci please test

@briancroom
Copy link
Contributor Author

@parkera I used corelibs-foundation as a model for adding a couple of types here (XCTestError and XCTPerformanceMetric) that are generated by the clang importer on Darwin. I just wanted to check that what I did here seems sensible to you.

Prior to Swift 4, several XCTest APIs were brought into Swift using the
`UInt` type, in contrast to other Apple system frameworks which consistently
used `Int`. In Swift 4, XCTest began being treated as a system framework
and now uses `Int` as well. This change adapts the swift-corelibs-xctest
API to match.
… function

This change was made in Xcode 9 as part of XCTest's Swiftification effort.
This is to match the struct generated by the Objective-C importer for
Apple XCTest due to its XCTestErrorCode having been marked with the
NSErrorDomain API note.
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.
@briancroom briancroom force-pushed the swift4-API-compatibility branch from d15f18c to 22e1c07 Compare August 15, 2017 17:13
@briancroom
Copy link
Contributor Author

@swift-ci please test

@briancroom
Copy link
Contributor Author

I updated this to no longer make the UInt -> Int change for the assertion functions. On Darwin, these functions come from the Swift XCTest overlay, rather than XCTest.framework, so the clang importer change due to making XCTest a system framework didn't affect them.

@briancroom
Copy link
Contributor Author

@swift-ci please test

@briancroom
Copy link
Contributor Author

@czechboy0 could you take a look here when you get a chance? Thanks!

Copy link
Member

@czechboy0 czechboy0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! I just added comments regarding the String/PerformanceMetric interaction.

self.metrics = metrics
self.delegate = delegate
self.invocationFile = file
self.invocationLine = line
}

static func measureMetrics(_ metricNames: [String], delegate: PerformanceMeterDelegate, file: StaticString = #file, line: UInt = #line, for block: (PerformanceMeter) -> Void) {
static func measureMetrics(_ metricNames: [String], delegate: PerformanceMeterDelegate, file: StaticString = #file, line: Int = #line, for block: (PerformanceMeter) -> Void) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not make metricNames: [PerformanceMetric] too? As they're strings, we have to map from PerformanceMetric to String down below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm..

One of the design goals with the PerformanceMeter and WallClockTimeMetric classes was for them to be entirely decoupled from the XCTest-specific stuff. i.e. they are conceptually a lower layer upon which the XCTest API sits. Ideally they would exist in their own separate module, but it's not currently possible to do that while still keeping XCTest library product and module standalone. See #109 for earlier discussion.

How do you feel about this given that context?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. A possible (future) improvement could be to create a similar enum at the PerformanceMeter layer.

guard _performanceMeter == nil else {
return recordAPIViolation(description: "Can only record one set of metrics per test method.", file: file, line: line)
}

PerformanceMeter.measureMetrics(metrics, delegate: self, file: file, line: line) { meter in
PerformanceMeter.measureMetrics(metrics.map({ $0.rawValue }), delegate: self, file: file, line: line) { meter in
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could get rid of this map if we move to [XCTPerformanceMetric] across the board.

@briancroom briancroom merged commit 2e96829 into swiftlang:master Aug 21, 2017
@krzyzanowskim
Copy link

It didn't make it to the Xcode9 GM either? I mean it works when building with Xcode, but not when launch test from the command line with "swift build"

Apple Swift version 4.0 (swiftlang-900.0.65 clang-900.0.37) Target: x86_64-apple-macosx10.9
Apple Swift Package Manager - Swift 4.0.0-dev (swiftpm-13126)

marcinkrzyzanowski:CryptoSwift (develop)$ swift test
Compile Swift Module 'CryptoSwiftTests' (13 sources)
/Users/marcinkrzyzanowski/Devel/CryptoSwift/Tests/CryptoSwiftTests/PBKDF.swift:59:29: error: type 'XCTPerformanceMetric' has no member 'wallClockTime'
            measureMetrics([XCTPerformanceMetric.wallClockTime], automaticallyStartMeasuring: true, for: { () -> Void in
                            ^~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants