【问题标题】:Can I run an XCTest suite multiple times?我可以多次运行 XCTest 套件吗?
【发布时间】:2015-09-20 15:01:19
【问题描述】:

是否可以让 Xcode 多次运行您的单元测试?

我在几个单元测试中遇到了导致间歇性故障的问题。现在我认为我已经修复了它,我唯一的选择似乎是混合 + U 直到我有 95% 的把握该错误是走了。

我知道其他单元测试框架可以很容易地多次运行单个测试、测试用例或测试套件。我们在 XCTest 中是否拥有这种奢侈?

【问题讨论】:

    标签: xcode unit-testing testing automated-tests xctest


    【解决方案1】:

    它可能会帮助你使用

    func testMultiple() {
        self.measureBlock() {
                ...
                XCTAssert(errMessage == nil, "no error expected")        
        }
    }
    

    这会多次运行 self.measureBlock() 中的代码来测量平均时间。

    更改代码是可行的,但您可能还是想知道执行时间。

    这个答案可能与您想要的足够接近,并且很容易做到。

    【讨论】:

    • 确实如此;我可以将每个测试包装在对measureBlock 的调用中,但是有谁知道该块在measureBlock 中执行了多少次?
    • 单元测试在您运行时会在控制台中告诉您。示例:测量的 [时间,秒] 平均值:0.002,相对标准偏差:154.282%,值:[0.011297, 0.001023, 0.000956, 0.000969, 0.000952, 0.000935, 0.000979, 0.000950, 0.0100968,0]
    • 我的回答不好的是测试不是随机混合的。如果您不时发生错误,则测试顺序可能会起作用。
    • 我想我可以将每个单独的测试包装在 measureBlock 块中,这样它们仍然会以随机顺序运行。感谢您和我一起研究这个;我认为这是我们可以用 XCTest 做的最好的事情。
    • 每次运行后是否调用 tearDown / setup,我假设不是。
    【解决方案2】:

    尝试使用for 循环:

    func testMultiple() {
        for _ in 0...100 {
                ...
                XCTAssert(errMessage == nil, "no error expected")        
        }
    }
    

    请注意,这在 self.measureBlock() 中不起作用。你会得到一个NSInternalConsistencyException: Cannot measure metrics while already measuring metrics

    但是,您可以在 measureBlock() 中调用它:

    func testMultiple() {
        for _ in 0...100 {
                ...
                XCTAssert(errMessage == nil, "no error expected")        
        }
    }
    
    func testPerformance() {
        self.measureBlock() {
            self.testMultiple()
        }
    }
    

    Xcode 8 运行 measureBlock 代码 10 次。

    【讨论】:

      【解决方案3】:

      另一种方法是通过命令行执行此操作。您可以使用 -only-testing 参数运行单个测试,并避免使用 test-without-building 进行构建,即(为清楚起见添加了新行)

      for i in {1..10}; \
        do xcodebuild \
          test-without-building \
          -workspace MyApp.xcworkspace \
          -scheme Debug \
          -destination 'platform=iOS Simulator,OS=11.2,name=iPhone 8' \
          -only-testing:MyApp.Tests/TestFile/myTest;
      done
      

      【讨论】:

        【解决方案4】:

        尝试覆盖调用测试:https://developer.apple.com/documentation/xctest/xctestcase/1496282-invoketest?language=objc

        - (void)invokeTest
        {
            for (int i=0; i<100; i++) {
                [super invokeTest];
            }
        }
        

        【讨论】:

          【解决方案5】:

          对我来说,它可以快速运行

          override func invokeTest() {
              for time in 0...15 {
                  print("this test is being invoked: \(time) times")
                  super.invokeTest()
              }
          }
          

          【讨论】:

          • 这在 Xcode 10 中对我很有用,但现在在 11 中没有任何运气。
          • 好吧,我已经测试过了,它在 xcode 11 中也适用于我
          • 我试过 11.3。现在在 11.4 beta 上,会再试一次。我会尝试一些琐碎的事情......
          【解决方案6】:

          我过去(Xcode 10)使用invokeTest() 覆盖取得了巨大成功。但现在在 Xcode 11 中它不起作用(至少对我来说)。我最终做的是:

          func test99Loop() {
              for i in 0..<LOOP_COUNT {
                  if i > 0 { tearDown(); sleep(1); setUp() }
                  test3NineUrls()
                  do { tearDown(); sleep(1) }
                  setUp()
                  test6NineCombine()
          
                  print("Finished Loop \(i)")
              }
          }
          

          我显然使用 setup/teardown,这是多次执行这些操作的正确方法(因为 Xcode 调用了第一个和最后一个)。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-05-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-07-27
            • 2019-11-12
            相关资源
            最近更新 更多