OCUnit是Xcode4.x的时候集成的测试框架。OCUnit中的测试分为两类,一类是Logic Tests,另一类是Application Tests。
Logic Tests更倾向于测试数据的流动,无关乎界面的逻辑部分,是个白盒测试;Application Tests更倾向于测试接口,尤其是和用户交互的接口,是个黑盒测试。当然实际情况并非非此即彼的一刀切的,但基本的区分思路是这样的。
OCUnit是Xcode集成的,当然和工程的结合是天生的最有优势的,最方便的。在创建新工程时就有一个Include Unit Tests的选项
如果钩上这个选项就会自动创建一个测试的Target。如果你的项目想增加一个测试Target,那么可以使用Add Target的方法,加入一个“Cocoa Touch Unit Testing Bundle”的Target就可以了。具体如图所示
加入Target会自动生成一个scheme,编译原工程和运行单元测试需要切换不同的scheme。
Logic Tests的话,到这里差不多就设置结束了,Application Tests设置会复杂一点,还需要继续进行一些设置,主要是Bundle Loader/Test Host以及scheme的设置,我这里先介绍一下这些设置,然后把例子的示意图对比贴出来。
在一个应用中,往往LogicTests和ApplicationTests是都需要的,由于两个测试的侧重点不同,所以建议是分开建立两个Target,这样scheme也会随着分成2个,设置起来也方便一点。下图是3个Target的样式
ApplicationTest还需要设置Bundle Loader和Test Host。
在Build Setting页面里面搜索Bundle Loader,并设置成$(BUILT_PRODUCTS_DIR)/APP_NAME.app/APP_NAME(APP_NAME是应用名)
在Test Host里面,设置成$(BUNDLE_LOADER)
下面是scheme的设置,不论LogicTest还是ApplicationTest的Scheme,都需要设置Scheme里面Test页面下设置测试项的内容,这个内容主要是从实际的TestCase里面来(TestCase命名是有规则的,这个稍后会讲到)。不同的是,ApplicationTest的项,需要在应用本身的Scheme的Test页面设置上。下面连续给出应用本身/LogicTest/ApplicationTest的Scheme示意图
设置到这里就告一段落,下面讲讲测试代码的书写。
为了让工具能自动识别,运行,对于测试代码的书写是有一定要求的,这个是由这个测试框架决定的。OCUnit运行必须包含SenTestingKit.framework这个库,针对需要测试的类,每个类写出自己的TestCase,独立组织一个文件。每个测试类都是继承自SenTestCase类,这里有3个重要的方法需要介绍:
1. -(void)setUp: 每个test方法执行前调用,用于类的创建,一些变量的初始化等
2. -(void)tearDown:每个test方法执行后调用
3. -(void)testXXX:这个是真正运行的测试方法,命名就是不带参数,以test开始。
这里的每个testXXX方法可以在Scheme里面看到,并可以设置是否测试这个方法
开发者的主要工作是自己实现这些无返回值的testXXX方法,一般框架会提供大量的断言方法,如果还是觉得不够丰富,可以使用第三方的库来进行扩充,比如:OCHamcrest。
LogicTest与ApplicationTest的区别主要在setUp方法,LogicTest仅仅需要在setUp方法中初始化一些测试数据,而ApplicationTest会需要在setUp方法中获得主应用的AppDelegate。这里还需要指出OCUnit的test bundle是侵入主应用的,因此使用的时候需要注意一下,不要让单元测试的资源覆盖主应用资源,造成一些莫名其妙的Bug。
顺带说一下,测试的TestCase类Xcode提供了标准的生成方法,有个“Objective-C test case class”的生成项。
测试的运行并非和主应用一样用Run方法,而是用Test方法,可以在Product-》Test菜单下运行,运行结果没有GUI显示,仅仅有log可以查询。log的查看可以用View-》Navigators-》Show Log Navigator。
最后,说明一下,我使用的例子是github上的HowsMyFuel,自己稍微进行了一点改动,测试学习的,给出网址如下:https://github.com/rlisle/HowsMyFuel