In this code
class MyXCTApplicationLaunchMetric: NSObject, XCTMetric {
let myLaunchMetric: XCTApplicationLaunchMetric
override init() {
myLaunchMetric = XCTApplicationLaunchMetric(waitUntilResponsive: true)
super.init()
}
// XCTMetric conformance
func willBeginMeasuring() {
myLaunchMetric.willBeginMeasuring()
}
// XCTMetric conformance
func didStopMeasuring() {
myLaunchMetric.didStopMeasuring()
}
// XCTMetric conformance
func reportMeasurements(from startTime: XCTPerformanceMeasurementTimestamp, to endTime: XCTPerformanceMeasurementTimestamp) throws -> [XCTPerformanceMeasurement] {
try myLaunchMetric.reportMeasurements(from: startTime, to: endTime)
}
// NSObject conformance
func copy(with zone: NSZone? = nil) -> Any {
self
// have also tried returning MyXCTApplicationLaunchMetric()
// and MyXCTApplicationLaunchMetric(myLaunchMetric) when provided
// an init that accepts that param.
}
}
When is called in
final class PerformanceUITests: XCTestCase {
func testLaunchPerformance() throws {
if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
let options = XCTMeasureOptions()
options.iterationCount = 1
measure(metrics: [MyXCTApplicationLaunchMetric()],
options: options) {
XCUIApplication().launch()
}
}
}
}
It crashes on line myLaunchMetric.willBeginMeasuring() with
Thread 2: "-[XCTApplicationLaunchMetric willBeginMeasuring]: unrecognized selector sent to instance 0x60000026c620"
I found that the selector error is typically caused because the instance does not have willBeginMeasuring() method. I also found that MyXCTApplicationLaunchMetric's init is called once and then the copy(with:), which is not clear why it would need a copy.