Xcode6下iOS单元测试——XCTest和GHUnit框架简介和比较

iOS单元测试(UnitTest)

在iOS中进行测试可以选择XCTest和GHUnit测试两种框架。XCTest集成在Xcode中,而GHUnit则是一个著名的开源框架。

所谓的单元测试,就是指把程序分割成若干个小单元,对每个小单元单独进行测试。所谓的小单元,可以是一个方法,一个UI控件,一次简单的事件等等。本文不重点讨论测试的意义,所以就选择最简单的加法函数,介绍iOS如何进行单元测试。

XCTest框架

XCTest介绍

XCTest的前身是OCUnit,它是一个集成在Xcode中的测试框架。它的使用比较简单,现在Xcode6默认建立的工程就带有XCTest。当然如果是旧的工程没有这个测试,或者不小心删了也没有关系,可以重新添加以下。

首先默认的测试名是“工程名 Tests”的格式。比如我们建立一个项目叫“ios练习”,默认的测试名就是“ios练习 Tests”。

接下来开始从零开始建立自己的单元测试。

XCTest配置

首先在项目设置的左下方,选择添加一个target:

然后在other列表内选择Cocoa Touch Testing Bundle。

Xcode6下iOS单元测试——XCTest和GHUnit框架简介和比较_第1张图片

选择finish即可创建一个新的target。成功添加之后可以看到新加了一个ios__Test.m文件,以及一个新的target。一般情况下系统会自动添加一个scheme,如果没有的话,也可以在左上角运行/停止键的旁边,点击一个scheme,选择新增scheme,并且选择对应的target。

这些配置做好了之后,应该是这样的:

Xcode6下iOS单元测试——XCTest和GHUnit框架简介和比较_第2张图片

图中标出的三个数字,是应该有的变动。

使用XCTest

基本配置做好了之后,就可以开始写代码,使用XCTest了。首先分析一下系统为我们创建的.m的文件:

#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>

@interface ios___Tests : XCTestCase

@end

@implementation ios___Tests

- (void)setUp {
    [super setUp];
    // Put setup code here. This method is called before the invocation of each test method in the class.
}

- (void)tearDown {
    // Put teardown code here. This method is called after the invocation of each test method in the class.
    [super tearDown];
}

- (void)testExample {
    // This is an example of a functional test case.
    XCTAssert(YES, @"Pass");
}

@end

与写ios不同的是,测试文件没有.h,因为并不需要这么复杂,类的声明在.m文件的@interface里面一起做了。比如这里我们创建了一个ios___Tests类继承自XCTestCase,所有的单元测试类都必须继承自这个基类。系统在执行单元测试的时候,会搜索所有XCTestCase的子类里面,以test开头的方法并执行这些方法。这时候,每一个以test开头的方法就是一个测试用例(TestCase)。比如这里的testExample方法就会当做一个测试用例被执行。

setUp和tearDown方法在每个测试用例的开始和结束时执行。这样可以简化大量代码。比如我需要测试操作数据库的一些方法,那么有必要在setUp方法里面连接数据库并且建表,在tearDown方法里删除表并关闭和数据库的连接。

接下来在ViewController里面添加一个简单的需要被测试的方法并在.h文件里面声明它:

//ViewController.h
- (int)addNumber:(int)a WithNumber:(int)b;

//ViewController.m
- (int)addNumber:(int)a WithNumber:(int)b {
    return a + b;
}

然后就可以在测试类里面开始测试这个方法了。

// ios___Tests.m
- (void)testAddMethodRight{
    ViewController *vc = [[ViewController alloc] init];
    int answer = [vc addNumber:1 WithNumber:2];  // answer = 3
    XCTAssertEqual(3, answer);
}

- (void)testAddMethodWrong{
    ViewController *vc = [[ViewController alloc] init];
    int wrongAnswer = 0;
    int answer = [vc addNumber:1 WithNumber:2];  // answer = 3
    XCTAssertEqual(wrongAnswer, answer);
}

这里的XCTAssertEqual是一个断言宏,简单来说就是如果它的两个参数值不等,就会报错。这也就是单元测试的目的所在。显然第二个测试无法通过。

接下来运行一下这个target,注意是通过Command + U快捷键运行。然后可以看到如下的运行结果:

Xcode6下iOS单元测试——XCTest和GHUnit框架简介和比较_第3张图片

Xcode非常贴心的帮我们标出了通过的(绿色的勾)和未通过的测试(红色的叉)。调试区还输出了非常详细的调试信息,包括每个测试失败的原因,测试运行的时间等。

以上就是简单的XCTest测试框架的使用。

GHUnit框架

GHUnit介绍

GHUnit是Github上一个非常有名的开源框架,但由于需要手动配置,所以相比于内置于Xcode的XCTest,稍微麻烦一些,不过它具有GUI,更加直白,功能也更强大一些。

配置GHUnit

首先前往https://github.com/gh-unit/gh-unit/downloads下载库文件,解压缩之后可以得到一个名为“GHUnitIOS.framework”的框架。待会儿需要用到这个框架。

接下来再新建一个target,注意target类型是一个普通的“Single Application View”,命名为“GHUnitTest”即可。注意由于Xcode认为这个是一个普通的应用,所以还会为他建立对应的XCTest,由于我们用不着,所以直接删除这个target和对应的文件即可。然后把刚刚下载并解压得到的GHUnitIOS.framework文件添加到GHUnitTest这个target下。配置好的界面如下:

Xcode6下iOS单元测试——XCTest和GHUnit框架简介和比较_第4张图片

可以看到GHUnitTest的图标和ios练习这个target的图标一致,因为它们都是“Single Application View”。

然后我们需要对这个普通的应用做一些修改,让它不普通起来,变成一个神奇的单元测试应用。首先删除AppDelegate文件,把.h和.m文件都删掉,然后把Supporting Files下的main.m文件改成这样:

#import <UIKit/UIKit.h>
#import <GHUnitIOS/GHUnitIOSAppDelegate.h>  //修改引用文件

int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([GHUnitIOSAppDelegate class]));// 这里改一下类名
    }
}

这里我们不再使用苹果自带的AppDelegate,而是使用GHUnit框架提供的GHUnitIOSAppDelegate。为了避免和主程序冲突,我们把GHUnitTest这个target里面的ViewController改名为GHUViewController。

至此,GHUnit框架的配置就完成了,比XCTest稍微复杂一些。接下来就开始写代码,使用这个框架了。

使用GHUnit

和XCTest框架一样,只需要.m而把类声明在.m文件里的@interface里即可。新建一个名为“MyGHUnitTestCase.m”的空的OC文件即可。在进行测试之前,需要把被测试的类加到GHUnitTest这个target的Compile Sources里

接下来声明一个名为MyGHUnitTestCase的类,并继承自GHTestCase。完整代码如下:

#import <Foundation/Foundation.h>
#import "ViewController.h"
#import <GHUnitIOS/GHTestCase.h>

@interface MyGHUnitTestCase : GHTestCase{

}

@end

@implementation MyGHUnitTestCase

- (void)setUp{

}

- (void)tearDown{

}

- (void)testAddMethodRight{
    ViewController *vc = [[ViewController alloc] init];
    int answer = [vc addNumber:1 WithNumber:2];  // answer = 3
    GHAssertEquals(answer, 3, @"answer的值应该为3");
}

- (void)testAddMethodWrong{
    ViewController *vc = [[ViewController alloc] init];
    int wrongAnswer = 0;
    int answer = [vc addNumber:1 WithNumber:2];  // answer = 3
    GHAssertEquals(answer, wrongAnswer, @"answer的值不应该为0");
}

@end

这个类的测试代码和此前介绍XCTest的时候,几乎一致,所以就不过多介绍了。Command + R运行一下。

Xcode6下iOS单元测试——XCTest和GHUnit框架简介和比较_第5张图片

GHUnit的GUI做的还是很不错的,有利于开发者调试问题,不过貌似没有适配IOS8…..

点击右上角的Run按钮,每个测试的成败、耗时都显示出来了。点击失败的测试,可以查看详细的方法调用堆栈。

Xcode6下iOS单元测试——XCTest和GHUnit框架简介和比较_第6张图片
Xcode6下iOS单元测试——XCTest和GHUnit框架简介和比较_第7张图片

总结

可以看到,XCTest的优势在于快捷方便的配置,而GHUnit的优势在于功能更加强大,因此推荐在进行比较大的项目的时候,考虑GHUnit测试框架。

你可能感兴趣的:(ios,单元测试,unittest,XCTest,GHUnit)