在Xcode 8中,使测试方法在给定的XCTestCase类中以特定顺序运行的方式是什么? [英] In Xcode 8, what is the way to make test methods run in a particular order within a given XCTestCase class?

查看:219
本文介绍了在Xcode 8中,使测试方法在给定的XCTestCase类中以特定顺序运行的方式是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Xcode 8之前,您可以通过按字母顺序给定XCTestCase类中的测试方法名称来使单元测试按特定顺序运行(如

Prior to Xcode 8, you could get your unit tests to run in a particular order by alphabetizing the names of the test methods within a given XCTestCase class (as described in this answer). E.g., tests would run like: testA, testB, testC, testD, etc.

但是在Xcode 8中,情况已不再如此.例如,我将首先运行名为test1,test2,test3,test4和test4的测试方法(请参见下面的屏幕截图).然后,我可以重新运行,并且test2将在下一个遍历中首先运行.

However in Xcode 8, this is no longer the case. For example I have test methods named test1, test2, test3, test4, and test4 will run first (see below screenshot). Then I can re-run, and test2 will run first on the next run-through.

那么如何使测试现在可以在Xcode 8上按顺序运行?

So how do I get the tests to run in order now on Xcode 8?

推荐答案

所以我解决此问题的方法如下.

So the way I solved this is as follows.

问题回顾:

我需要连续运行多个测试:test1test2test3test4.每个测试都设置了期望,并且测试的最后一步将满足期望,然后测试结束并运行下一个.

I needed to have several tests run in a row: test1, test2, test3, test4. Each test set up an expectation and the final step in the test would fulfill the expectation, then the test would conclude and the next one would run.

但是,在Xcode 8中,测试现在以随机顺序运行.从观点来看,这很好,但如果它们是单元测试,它们应该能够以随机顺序运行,但是如果它们不是设计为单元测试,而是设计为 end,则会破坏您的测试.到结束测试.

However in Xcode 8, tests now run in random order. While that's good from the standpoint that, if they are unit tests, they should be able to run in random order, it breaks your tests if they are designed not as unit tests, but as end-to-end tests.

例如,在我的案例中,它破坏了测试,因为在第一个测试中,用户登录并设置了一些数据等.然后,第二个测试检查了数学,然后第三个测试将数据同步到服务器,然后第四个将其全部删除并从服务器同步下来.当第一个测试运行时,在构建时,shell脚本从MSYQL文件启动服务器的数据库,然后在应用程序启动时,AppDelegate为应用程序安装新的Core Data DB.因此,如果我必须在每次测试后重新启动应用程序,则外壳程序脚本将重新初始化服务器数据库,并使应用程序的本地Core Data DB也重新初始化.这将破坏后续测试(在之前的测试运行之后,后续测试取决于应用程序和服务器的状态,这是端到端测试).

For example in my case it breaks the tests because in the first test, a user logs in and set up some data etc. Then, the second test checks the math, then the third test syncs the data to a server, then the fourth one deletes it all and syncs down from the server. When the first test runs, at build time, a shell script inits the server's DB from a MSYQL file, then at launch time of the app, the AppDelegate installs a fresh Core Data DB for the app. So, if I have to launch the app fresh after each test, the shell script will re-init the server DB and cause the app's local Core Data DB to also re-init. This will break the subsequent tests (it being an end-to-end test the subsequent tests depend on the state of the app and server being a certain way, after the previous test ran).

与其设置四个不同的Core Data启动数据库和四个不同的服务器初始化脚本(这将是一个巨大的痛苦,并且使端到端测试在进行模式更改时要成倍地耗费更多的管理时间),或必须记住运行时不要连续手动构建每个测试,而是使用以下策略将所有四个测试方法合并为一个非常长的测试方法.

Rather than set up four different Core Data starting DBs and four different server init scripts (which would have been a huge pain and made the end-to-end test exponentially more time consuming to manage whenever we have a schema change), or have to remember to run without building each test manually in a row, instead I merged all four test methods into a single really long test method using the following tactic.

解决方案

首先,在XCTestCase类中,我设置了一个测试期望属性:

First, in the XCTestCase class, I set up an test expectation property:

@property (nonatomic, strong) XCTestExpectation *endOfTestExpectation;

在我的XCTestCase类的test1的结尾,我用这个新期望替换了它的现有期望,就像这样:

At the end of the test1 in my XCTestCase class, I replaced its existing expectation with this new expectation, like so:

self.endOfTestExpectation = [self expectationWithDescription:
                                  @"endOfTestExpectation"];

[self waitForExpectationsWithTimeout:900 
                             handler:^(NSError * _Nullable error) {
    /* Code moved from test4's expectation completion block goes here */
}

对于每个test1test3,我将测试的原始期望完成块中的代码移到了名为completion1completion3的新方法中.对于test4,我在test1方法末尾将其原始期望完成块中的代码移到了endOfTestExpectation的完成块中.

For each test1 through test3, I moved the code that was inside the test's original expectation completion block into a new method called completion1 through completion3. For test4 I moved the code inside its original expectation completion block into the endOfTestExpectation's completion block at the end of the test1 method.

然后,我将方法test2test4重命名为t3st2t3st4(我知道这是快速又肮脏的;在它起作用后,您应该选择更具描述性的内容).在completion1方法的末尾,我调用t3st2;在completion2的结尾,我叫t3st3;在completion3的结尾,我叫t3st4;在completion4的结尾处我叫[self.endOfTestExpectation fulfill];.

Then I renamed the methods test2 through test4 to be named t3st2 through t3st4 (quick and dirty, I know; you should pick something more descriptive after you get it working). At the end of the completion1 method, I call t3st2; at the end of completion2 I call t3st3; at the end of completion3 I call t3st4; and at the end of completion4 I call [self.endOfTestExpectation fulfill];.

这实际上比旧方法要好,因为以旧方法,即使第一个测试失败,后续的测试仍将运行!现在,无论XCTFail发生在哪里,整个过程都将停止,并且如果我进入Tab:D

This actually ends up being better than the old way, because in the old way, even if the first test failed, the subsequent tests would still run! Now, wherever an XCTFail happens, the entire thing just stops and we don't waste time running the rest if I was tabbed over into SO :D

这篇关于在Xcode 8中,使测试方法在给定的XCTestCase类中以特定顺序运行的方式是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆