swifttestingxctestxctestcase

Custom Launch Metric Not Reporting Expected Results


I would like to have "access" to the reported measurements in XCTApplicationLaunchMetric. To this effect, I created my own class that adopts XCTMetric and uses, calls XCTApplicationLaunchMetric under the hood like this:

class MyXCTApplicationLaunchMetric: NSObject, XCTMetric {
    let myLaunchMetric: XCTApplicationLaunchMetric

    init(waitUntilResponsive: Bool) {
        print(#function)
        myLaunchMetric = XCTApplicationLaunchMetric(waitUntilResponsive: waitUntilResponsive)
    }

    // XCTMetric conformance
    func willBeginMeasuring() {
        print(#function)
        myLaunchMetric.willBeginMeasuring()
    }

    // XCTMetric conformance
    func didStopMeasuring() {
        print(#function)
        myLaunchMetric.didStopMeasuring()
    }

    // XCTMetric conformance
    func reportMeasurements(from startTime: XCTPerformanceMeasurementTimestamp, to endTime: XCTPerformanceMeasurementTimestamp) throws -> [XCTPerformanceMeasurement] {
        let measurement = Measurement(value: 40, unit: .init(symbol: "M"))
        let performanceMeasurement = XCTPerformanceMeasurement(identifier: "SomeIdentifier", displayName: "SomeDisplayName", value: measurement)
        return [performanceMeasurement]
    }

    // NSObject conformance
    func copy(with zone: NSZone? = nil) -> Any {
        myLaunchMetric.copy(with: zone)
    }
}

However, when I use it here, none of the XCTMetric functions are called. The init is called. I am not sure why.

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

            let launchMetric = MyXCTApplicationLaunchMetric(waitUntilResponsive: true)
            measure(metrics: [launchMetric],
                    options: options) {
                XCUIApplication().launch()
            }
        }
    }
}

Solution

  • The reason is because measure calls copy(with:) and you are not returning an instance of your custom type but myLaunchMetric which is an instance of XCTApplicationLaunchMetric.