单元测试,从陌生到熟悉

单元测试,从陌生到熟悉

  • 什么是单元测试?

相信我们做开发这么久,对这个也比较陌生,听起来很高端的样子。其实单元测试就是为你的方法多专门写一个测试函数。以保证你的方法在不停的修改开发中。保持正确。如果出错,第一时间让你知道,这样从最小单位开始监控来保证软件的质量。

  • 什么时候用到单元测试

1、写完代码以后:想要验证一下自己写的代码是否有问题。

2、写代码之前:就是写代码之前所有的功能分模块的设计好,测试通过了再写。

3、修复某个bug后:一般修复完某个bug,为了确保修复是成功的,会写测试。

  • 废话少说了,立刻上实例! XCTest 的简单用法

开始

在xcode新建项目中,默认都会给你建一个单元测试的target,如果你的项目没有,可以在导航中选择 File->New->Target->选择ios-test->选择iOS Unit Testing Bundle 新建一个测试target。所有的测试类都必须继承 XCTestCase 类。

其中有几点需要大家注意:

  • 该类中以test开头的方法且void返回类型的方法都会变成单元测试用例(我们编写自定义的测试方法也必须用 test 开头,系统才能识别)
  • 单元测试类继承 XCTestCase,每个类都有很重要的三个方法setUp taerDown measureBlock
//每次测试前调用,可以在测试之前创建和初始化在test case方法中需要用到的一些对象等
- (void)setUp ;
//每次测试结束时调用tearDown方法,释放掉我们创建的资源
- (void)tearDown ;

//性能测试方法,通过测试block中方法执行的时间,比对设定的标准值和偏差觉得是否可以通过测试
measureBlock

断言

大部分的测试方法使用断言决定的测试结果。所有断言都有一个类似的形式:比较,表达式真假,强行失败,设定固定阈值等。断言的形式有如下 api:

//通用断言
XCTAssert(expression, format...)
//常用断言:
XCTAssertTrue(expression, format...)
XCTAssertFalse(expression, format...)
XCTAssertEqual(expression1, expression2, format...)
XCTAssertNotEqual(expression1, expression2, format...)
XCTAssertEqualWithAccuracy(expression1, expression2, accuracy, format...)
XCTAssertNotEqualWithAccuracy(expression1, expression2, accuracy, format...)
XCTAssertNil(expression, format...)
XCTAssertNotNil(expression, format...)

XCTFail(format...) //直接Fail的断言

举个小栗子:

- (void)testAge
{
    _p.age = -10;
    XCTAssertTrue(_p.age > 0,"年龄不能是负数");
}

- (void)testWeight
{
    _p.weight = 50.0;

    [_p keepfit:10.0];
    
    XCTAssertEqual(40, _p.weight,"成功减重10公斤");

}

一个测试用例比较规范的写法,1:定义变量和预期,2:执行方法得到实际值,3:断言

性能测试

性能测试主要使用 measureBlock方法,用于测试某组方法的执行时间,可以通过设置baseline(基准)stddev(标准偏差)来判断方法是否能通过性能测试:

- (void)testPerformanceExample {
    // This is an example of a performance test case.
    [self measureBlock:^{
          //Put the code you want to measure the time of here.
          //需要进行性能测试的代码和方法
    }];
}

异步测试

测试异步方法时,因为结果并不是立刻获得,所以在异步方法测试有一些特殊的api 和技巧。

举个大栗子:

- (void)testAsynExample {
    XCTestExpectation *exp = [self expectationWithDescription:@"这里是操作出错的原因描述。。。或者其它描述"];
    
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    [queue addOperationWithBlock:^{
        //模拟这个异步操作需要2秒后才能获取结果,比如一个异步网络请求
        sleep(2);
        //模拟获取的异步操作后,获取结果,判断异步方法的结果是否正确
        XCTAssertEqual(@"a", @"a");
        //如果断言没问题,就调用fulfill宣布测试满足
        [exp fulfill];
    }];

    //设置延迟多少秒后,如果没有满足测试条件就报错
    [self waitForExpectationsWithTimeout:3 handler:^(NSError * _Nullable error) {
        if (error) {
            NSLog(@"Timeout Error: %@", error);
        }
    }];
}

这个测试肯定通过的,因为设置延迟为3秒,而异步操作2秒就给出了一个正确的结果,并宣布了条件满足[exp fulfill],但是当我们把延迟改成1秒,这个测试用例就不会成功,错误原因是 expectationWithDescription:@"这里操作出错的原因描述。。。
异步测试还可以使用expectationForPredicateexpectationForNotification这两个方法。

执行测试快捷键

  • command + 5 切换到测试选项卡后出现很多小箭头,点击可以单独测试或整体测试
  • command + U运行整个单元测试

注意点

  • 使用 pod 的项目中,在 XC 测试框架中测试内容包含第三方包的时候,需要手动去设置 Header Search Paths才能找到头文件,还需要设置test targetPODS_ROOT路径。
  • Xcode7及以上版本使用真机跑测试的时候,必须配好证书,否则会报exc_breakpoint错误。

可以看一下我的示例代码:
代码示例

UI Test

UITest 是随着 Xcode7被推出来的,主要功能是页面的 UI 测试,相比以前使用 JavaScript编写 的 UIAutomation(已被弃用),UITest 可以用 OC 或 Swift 我们熟悉的语言编写 UI 测试代码。UITest 最大的亮点是支持屏幕录制--通过对 app 的操作,自动生成相应的测试脚本代码。

UI Test 的工作原理,对于一般的 UIKit 对象,Apple 提供 XCUIElement 对象作为映射。我们只能通过 Accessibility 的 identifier 等属性来获取 UI 信息。

  • UITest 核心的类有三个 XCUIApplication,XCUIElement,XCUIElementQuery

    • XCUIApplication是Application的代理,用来启动或者是终止UI测试程序.启动参数设置,在获取程序中的UI元素。
    • XCUIElement是XCTest.framework对应用中的所有UI控件的抽象,所有的UI控件都是此类型,滑动,点击,轻扫手势
    • XCUIElementQuery是查询UI的类,通过类似key-value的机制得到XCUIElement的实例,使用Type(XCUIElementType枚举),Predicate,Identifier创建query,使用elementAtIndex:, elementMatchingPredicate,elementMatchingType: identifier:方法访问匹配到的UI元素,同样遵循了XCUIElementTypeQueryProvider协议.

UI Test 主要是解放我们的双手,不用每次测试一个 UI 业务逻辑,就反复启动 app 的去点击跳转等。


逐个测试.png

整个 UI Test 中最难的部分,当属于查找 UI 元素,其它操作看起来就是自然语言一般,找到哪个控件,执行什么交互动作。

通过上述,示例,我们可以开始愉快的为我们的程序编写单元测试和录制 UI 测试的代码了(虽然以前很不情愿写测试代码,但是哭着也要写完啊。)

参考:

iOS-UITest 测试

iOS-使用Xcode自带单元测试UnitTest

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,657评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,889评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,057评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,509评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,562评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,443评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,251评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,129评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,561评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,779评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,902评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,621评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,220评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,838评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,971评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,025评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,843评论 2 354

推荐阅读更多精彩内容