1

作为我正在编写的UI测试的一部分,我想测量一个功能的性能。测试本身需要一段时间,而且我要测量的部分很小,而且测试运行的频率足够高,每次运行只需进行一次测量即可获得所需的数据。但是, XCTestCasemeasure(_:)将运行 10 次。

是否有任何选项我可以给它或measureMetrics(_:automaticallyStartMeasuring:for:)只运行一次测量,或者有什么方法让我自己进行测量并将其反馈到测试运行器中,以便它像 Xcode 那样集成measure(_:)

4

1 回答 1

1

这很烦人。

尽管在 Xcode 11 中,您可以指定XCTMeasureOptions何时调用self.measure { },即measure(options: XCTMeasureOptions, block: () -> Void). 在 中options,您可以设置iterationCount为 1。

但!

iterationCount根据以下文档,设置为 1,Xcode 实际上会运行两次测量块iterationCount

性能测试运行其块迭代Count+1 次,忽略第一次迭代并记录剩余迭代的指标。该测试忽略第一次迭代以减少与“预热”缓存和其他首次运行行为相关的测量方差。

它在实践中确实运行了两次。

同时iterationCount根据文档设置为 0 不会产生任何结果:

... iterationCount+1 次,忽略第一次迭代并记录剩余迭代的指标

我不知道更改测量计数的Runtime Swizzling 方式是否可以摆脱热身运行。

解决方法

设置一个计数器以...

  1. 跳过第一次运行:
    func testYourFunction() {
        let option = XCTMeasureOptions()
        option.iterationCount = 1
        var count = 0
        self.measure(options: option) {
            if count == 0 {
                count += 1
                return
            }
            // Your test code...
        }
    }
  1. 回滚更改:
    func testYourFunction() {
        let option = XCTMeasureOptions()
        option.iterationCount = 1
        var count = 0
        self.measure(options: option) {
            defer {
                if count == 0 {
                    try? setUpWithError()
                    // call `setUpWithError` manually
                    // or run your custom rollback logic
                }
                count += 1
            }
            // Your test code...
    }
于 2020-11-27T05:37:48.747 回答