在XCode 8之前,您可以通过按字母顺序排列给定XCTestCase类中的测试方法的名称来使您的单元测试按特定顺序运行(如this answer中所述)。例如,测试将运行如:testA,testB,testC,testD等。
但是在XCode 8中,情况已不再如此。例如,我将首先运行名为test1,test2,test3,test4和test4的测试方法(参见下面的屏幕截图)。然后我可以重新运行,test2将在下一次运行时首先运行。
那么......如何在XCode 8上按顺序运行测试......?
答案 0 :(得分:6)
所以我解决这个问题的方法如下。
问题回顾:
我需要连续进行多项测试:test1
,test2
,test3
,test4
。每个测试都设定了一个期望,测试的最后一步将满足期望,然后测试结束,下一个测试将运行。
然而,在XCode 8中,测试现在以随机顺序运行。虽然这是好的,但是如果它们是单元测试,它们应该能够以随机顺序运行,如果它们不是作为单元测试设计,而是作为结束,它会破坏你的测试到结束测试。
例如在我的情况下,它会破坏测试,因为在第一次测试中,用户登录并设置一些数据等。然后,第二个测试检查数学,然后第三个测试将数据同步到服务器,然后第四个删除它并从服务器同步。当第一个测试运行时,在构建时,shell脚本从MSYQL文件进入服务器的DB,然后在应用程序启动时,AppDelegate为应用程序安装一个新的CoreData DB。因此,如果我必须在每次测试后重新启动应用程序,那么shell脚本将重新启动服务器数据库并导致应用程序的本地CoreData数据库也重新初始化。这将打破后续测试(它是一个端到端测试,后续测试依赖于应用程序和服务器的状态,在上一次测试运行后以某种方式)。
而不是设置四个不同的CoreData启动数据库和四个不同的服务器初始化脚本(这将是一个巨大的痛苦,并且当我们进行架构更改时,管理端到端测试会更加耗时),或者必须记住在不连续手动构建每个测试的情况下运行,而是使用以下策略将所有四种测试方法合并为一个非常长的测试方法。
<强>解决方案强>
首先,在XCTestCase类中,我设置了一个测试期望属性:
@property (nonatomic, strong) XCTestExpectation *endOfTestExpectation;
在我的XCTestCase类的test1
结束时,我用这个新的期望替换了它的现有期望,如下所示:
self.endOfTestExpectation = [self expectationWithDescription:
@"endOfTestExpectation"];
[self waitForExpectationsWithTimeout:900
handler:^(NSError * _Nullable error) {
/* Code moved from test4's expectation completion block goes here */
}
对于每个test1
到test3
,我将测试原始期望完成块中的代码移动到名为completion1
到completion3
的新方法中。对于test4
,我将原始期望完成块中的代码移动到endOfTestExpectation
方法末尾的test1
完成块中。
然后我将方法test2
重新命名为test4
,通过t3st2
命名为t3st4
(快速而肮脏,我知道;你应该选择更具描述性的方法)它工作)。在completion1
方法结束时,我致电t3st2
;在completion2
结束时,我致电t3st3
;在completion3
结束时,我致电t3st4
;在completion4
结束时,我致电[self.endOfTestExpectation fulfill];
。
这实际上最终比旧方法更好,因为在旧的方式中,即使第一次测试失败,后续测试仍然会运行!现在,无论XCTFail
发生了什么,整个事情就会停止,如果我被标记为SO:D