IOS --Xcode6单元测试

单元测试,又称模块测试。是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。面向过程编程,一个单元就是单个程序;面向对象编程,程序最小单位是方法。

XCTest是Xcode内置的测试框架。同时,Xcode6新增XCTestExpectation和性能测试。

xcode6创建一个新的工程后,项目会自动配置两个group:一个是“工程名称”group;另一个是“工程名称Test”group。它们分别对应两个target,一个是运行的target,另一个是测试的target。用户使用Command+R编译运行的target,使用Command+U编译测试的target。

在测试的group中,有一个工程名称test.m文件,这个文件里面包含一个XCTestCase类,里面有四个方法:setUp、tearDown、testExample、testPerformanceExample。

XCTestCase

xcode的单元测试包含在XCTestCase的子类中,组织测试的时候尽量需要考虑实际的应用操作流程。

setUp & tearDown

setUp方法在XCTestCase的测试方法调用之前调用。当全部测试结束之后调用tearDown方法。

- (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];
}

setUp方法可以在测试之前创建一些 在test case中需要用到的一些对象等。tearDown方法则在全部的test case执行结束后清理测试现场,释放资源、删除不用的对象等。

功能测试

test case中的每一个方法都是以test开头,这样容易辨别。方法中会执行断言Assert来判断这个测试是否通过。

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

常用的XCTest断言

XCTest会用到很多断言,这里列举一部分。

基本测试

所有的断言都是从最基本的这个断言演化出来的:

XCTAssert(expression,format……)

如果expression(表达式)执行结果为true的话,这个测试通过;否则,测试失败,并在控制台输出后面的format字符串。

Bool测试

对于bool型的数据,或者只是简单的bool型表达式,使用XCTestAssertTrue或XCTestAssertFalse。

相等测试

测试两个值是否相等使用XCTAssert[NO]Equal

XCTAssertEqual(expression1,expression2,format……)

在处理double、float类型数据的对比时使用XCTAssert[Not]EqualWithAccuracy来处理浮点精度的问题。

nil测试

使用XCTAssert[Not]Nil来判断给定的表达式值是否为nil。

无条件失败断言

使用XCTFail测试无条件断言

XCTFail(format……)

XCTFail,无条件的都是测试失败。这个东东有什么用处呢?在测试里面有这么个情况,我们定义了测试方法,但是没有给出具体的实现,那么我们肯定不会希望这个测试能顺利通过。是的,XCTFail就是这个用途。一般被用作一个占位断言,等我们的测试方法完善好了之后在换成最贴近我们测试的断言。再或者,在某些情况下else了之后就是不应该出现的情况,那么这个时候可以将XCTFail放在这个else里面。

性能测试

性能测试可以帮助开发者建立一个主要功能的基本性能基线,确保这些主要功能代码和算法能在这个性能基线内完成。

XCTestExpectation

XCTestExpectation是xcode自带的异步测试类。即现在测试可以等待指定长度的时间,一直到某些条件符合的时候再开始测试,而不用再写很多的GCD代码控制。

要使用异步测试,首先用方法expectationWithDescription创建一个expection。

let expectation = expectationWithDescription("……")

之后在方法的最后添加方法waitForExpectationsWithTimeOut,指定等待超时的时间和指定时间内条件无法满足时执行的closure。

waitForExpectationsWithTimeOut(10) {(error) in ……}

接下来就是在异步测试剩下的回调函数中告诉expectation条件已经满足。

expectation.fulfill()

如果在测试中有多个expectation,则每个expectation都必须fulfill,否则测试不通过。

func testAsynchronousURLConnection(){
        let URL = NSURL(string: "http://www.baidu.com")!
        let expectation = expectationWithDescription("GET \(URL)")
        let session = NSURLSession.sharedSession()
        let task = session.dataTaskWithURL(URL, completionHandler: {(data, response, error) in
            expectation.fulfill()   // 告诉expectation满足测试了
            XCTAssertNotNil(data, "返回数据不应该为空")
            XCTAssertNil(error, "error应该为nil")
            if response != nil {
                var httpResponse: NSHTTPURLResponse = response as NSHTTPURLResponse
                XCTAssertEqual(httpResponse.URL!.absoluteString!, URL, "HTTPResponse的URL应该和请求URL一致")
                XCTAssertEqual(httpResponse.statusCode, 200, "HTTPResponse状态码应该是200")
                XCTAssertEqual(httpResponse.MIMEType as String, "text/html", "HTTPResponse内容应该是text/html")
            }
            else{
                XCTFail("返回内容不是NSHTTPURLResponse类型")
            }
        })
        task.resume()
        waitForExpectationsWithTimeout(task.originalRequest.timeoutInterval, handler: {error in
            task.cancel()
        })
    }

总结

xcode内置工具已经很好了,即使很大的app也没有必要为了单元测试的代码覆盖率而排斥xcode内置工具。即无论怎么样的测试,XCTest的各种断言、expectation和性能测试都足以应付。

如果在测试IOS或者OS X的APP,开始为自动添加的测试类添加一些断言并按下Command+U。我们就会发现xocde自带的工具让我们测试很方便。


断言测试

  1. 测试方法的要求:1>必须无返回值;2>以test开头

  2. 测试方法执行的顺序:以方法名中test后面的字符大小有关,例如:

    -(void)test001XXX会优于-(void)test002XXX执行

  3. 运行单元测试快捷键:Command+U

下面一共有18个断言(SDK中也是18个)

XCTFail(format……)生成一个失败的测试

XCTAssertNil(a1,format……)判空,a1为空时通过,反之不通过。

XCTAssertNotNil(a1,format……)判不为空,a1不为空时通过,反之不通过

XCTAssert(expression,format……)当expression求值为true时,测试通过。

XCTAssertTrue(expression,format……)当expression求值为true时,测试通过

XCTAssertFalse(expression,format……)当expression求值为False时,测试通过

XCTAssertEqual(a1,a2,format……)判断相等,相等时测试通过

XCTAssertNotEqual(a1,a2,format……)判断不等,不等时测试通过

XCTAssertEqualObjescts(a1,a2,format……)判断相等,[a1 isEqual:a2]值为True时通过,其中一个为空时不通过。

XCTAssertNotEqualObjescts(a1,a2,format……)判断不等,[a1 isEqual:a2]值为False时通过

XCTAssertEqualWithAccuracy(a1,a2,accuracy,format……)判断相等,(double或float类型)提供一个误差范围,在误差范围(+/-accuracy)以内相等时测试通过。

XCTAssertNotEqualWithAccuracy(a1,a2,accuracy,format……)判断不等,(double或float类型)提供一个误差范围,在误差范围(+/-accuracy)以内不等时测试通过。

XCTAssertThrows(expression,format……)异常测试,当expression发生异常时通过,反之不通过

XCTAssertNotThrows(expression,format……)异常测试,当expression没有发生异常时通过,反之不通过

XCTAssertThrowsSpecific(expression, specificException, format...) 异常测试,当expression发生specificException异常时通过;反之发生其他异常或不发生异常均不通过

XCTAssertNoThrowSpecific(expression, specificException, format...)异常测试,当expression没有发生具体异常、具体异常名称的异常时通过测试,反之不通过

XCTAssertThrowsSpecificNamed(expression, specificException, exception_name, format...)异常测试,当expression发生具体异常、具体异常名称的异常时通过测试,反之不通过

XCTAssertNoThrowSpecificNamed(expression, specificException, exception_name, format...)异常测试,当expression没有发生具体异常、具体异常名称的异常时通过测试,反之不通过

举例子应用

//1.比较基本数据类型

XCTAssertEqual(1,2,@"a1 = a2 shoud be true");//测试没通过

XCTAssertEqual(1,1,@"a1 = a2 shoud be true");//测试通过

//2.如果a1,a2是指针,则当他们指向同一个对象时才会返回YES,如下:

NSArray *array1 = @[@1];

NSArray *array2 = @[@1];

NSArray *array3 = array1;

XCTAssertEqual(array1,array2,@"a1 and a2 shoulid point to the same object");//测试不通过

XCTAssertEqual(array1,array3,@"a1 and a2 shoulid point to the same object");//测试通过

//3.要注意使用NSString

NSString *str1 = @"1";

NSString *str2 = @"2";

NSString *str3 = str1;

XCTAssertEqual(str1,str2,@"a1 and a2 shoulid point to the same object");//测试通过

XCTAssertEqual(str1,str3,@"a1 and a2 shoulid point to the same object");//测试通过

尽管str1与str2指向不同的对象,但是二者的指针比较依然通过了测试。由于str1与str2指向同一个常量,常量在data段中地址是固定的,所以二者地址相同。




你可能感兴趣的:(IOS --Xcode6单元测试)