我能否多次运行XCTest测试套件?

13

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

我有几个单元测试出现了间歇性故障。现在,我认为我已经解决了这个问题,但我的唯一选择似乎是一遍又一遍地按下 + U,直到我有95%的信心这个错误已经消失。

我知道其他单元测试框架很容易多次运行单个测试、测试用例或测试套件。那么,在XCTest中我们是否也能拥有这种便利呢?

8个回答

12

对我来说,它在Swift中有效。

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

这在Xcode 10中对我非常有效,但现在在11中没有任何运气。 - David H
好的,我已经测试过了,在Xcode 11中也能正常工作。 - Sultan Ali
我尝试了11.3版本。现在使用的是11.4测试版,稍后会再次尝试。我将尝试一些简单的东西... - David H
这在 Xcode 14.1 中工作。 - Matea

7

4

Xcode有一种内置的方法可以做到这一点:

右键单击测试,然后选择重复运行<test>...

enter image description here

那个菜单有几个配置选项之一是 Stop After,您可以选择 Failure,如果在重复执行的过程中失败,将停止执行。

您还可以重复运行测试类或整个测试套件。


1
当我提出这个问题时,Xcode显然没有这个功能,但现在它有了,真是太棒了! - undefined

4

可能会对您有帮助,使用:

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

这将在多次运行self.measureBlock()内的代码以计算平均时间。

改变代码可能需要一些工作,但您可能仍然希望了解执行时间。

这个答案可能已经足够接近您想要的,并且很容易实现。


1
没错;我可以将每个测试都包装在对 measureBlock 的调用中,但有人知道在 measureBlock 中块被执行了多少次吗? - T Blank
单元测试在运行时会在控制台中告诉您。例如:测量[时间,秒]平均值:0.002,相对标准偏差:154.282%,值:[0.011297、0.001023、0.000956、0.000969、0.000952、0.000935、0.000979、0.000950、0.000968、0.001042]。 - Gerd Castan
我的回答有问题的地方在于测试用例没有随机混合。如果你时不时遇到错误,测试用例的顺序可能会起作用。 - Gerd Castan
我想我可以将每个单独的测试都包装在一个 measureBlock 块中,这样它们仍然会以随机顺序运行。感谢您与我一起研究此问题;我认为这是我们在 XCTest 中能做到的最好的方法。 - T Blank
这个调用tearDown/setup在每次运行后都会执行吗?我猜想不会。 - gran_profaci
不要在方法内部执行。 - Gerd Castan

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

1

现在你可以在Xcode中完成这个操作

编辑测试计划。在测试导航器中,顶部应该会看到“测试计划:MyAppName(默认)”。点击它并选择“编辑测试计划”。

在编辑器中,选择配置,配置1

在测试执行下,您可以设置测试重复模式和最大测试重复次数。

从菜单产品 > 测试运行测试

enter image description here


谢谢你的回答!当我提问时,Xcode还没有这个功能,但很高兴看到现在支持测试重复。 - undefined

0
尝试使用 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 次。


0

我过去曾经非常成功地使用invokeTest()覆盖(Xcode 10)。但是现在在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调用)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接