单元测试

目录

<a name="前言"></a>前言

在日常的开发中,单元测试是很关键的一环。因为它可以帮你省去很多的重复测试工作,特别是在接口上(防止后台坑你..,也防止自己坑自己)。即使在第一个版本开发时间急的情况下,也得在第二个版本补上。

<a name="断言语法"></a>断言语法

单元测试的关键点在于 "断言"。在"XCTest"类中,你可以看到全部的断言。本篇文章将全部采用swift语言讲解。

  • XCTAssert : 最常用的断言

    • 如 XCTAssert(1 < 2) 可通过
  • XCTAssertEqual : 断言 "="

    • 如 XCTAssertEqual("1", "1") 可通过
  • XCTAssertEqualWithAccuracy : 断言 "=" 允许误差

    • 如 XCTAssertEqualWithAccuracy(1, 2, accuracy: 1) 可通过
  • XCTAssertFalse 断言 "flase"

    • 如 XCTAssertFalse(false) 可通过
  • XCTAssertTrue 断言 "true"

    • 如 XCTAssertTrue(true) 可通过
  • XCTAssertGreaterThan 断言 ">"

    • 如 XCTAssertGreaterThan(2, 1) 可通过
  • XCTAssertGreaterThanOrEqual 断言 ">="

    • 如 XCTAssertGreaterThanOrEqual(1, 1) 可通过
  • XCTAssertLessThan 断言 "<"

    • 如 XCTAssertLessThan(1, 2) 可通过
  • XCTAssertLessThanOrEqual 断言 "<="

    • 如 XCTAssertLessThanOrEqual(1, 2) 可通过
  • XCTAssertNotEqual 断言 "!="

    • 如 XCTAssertNotEqual(1, 2) 可通过
  • XCTAssertNotEqualWithAccuracy 断言 "!=" 允许误差

    • 如 XCTAssertNotEqualWithAccuracy(1, 2, 0.5) //1 + 0.5(误差) != 2 可通过
  • XCTAssertNotNil 断言 "! = nil"

    • 如 XCTAssertNotNil(1) 可通过
  • XCTAssertThrowsError 直接抛出错误,不通过

  • XCTFail 直接测试失败 不通过

<a name="配置"></a>配置

在测试文件中有两个初始的方法setUp 和 tearDown。

  • setUp 在每个测试被调用都会调用,所以一般涌来配置一些设置,如网络请求配置。
  • tearDown 在测试被调用之后调用,一般不需要关心。
    override func setUp() {
        super.setUp()
        // Put setup code here. This method is called before the invocation of each test method in the class.
    }
    
    override func tearDown() {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
        super.tearDown()
    }

<a name="添加测试"></a>添加测试

在项目中的test文件中添加 以test开头的函数即可,如:

     func testCommon()  {
         XCTAssertTrue(1 < 2)
     }

然后点击左上角的执行图标,就可以测试啦。
如下图


屏幕快照 2017-03-01 下午1.19.44.png

测试结果为绿色的图标就是测试通过。
如下图


屏幕快照 2017-03-01 下午1.16.22.png

如果测试不通过,对应的代码会报错。
如下图
屏幕快照 2017-03-01 下午1.20.06.png

当然你还可以通过侧栏对其全部或单个测试。
如下图


屏幕快照 2017-03-01 下午1.23.58.png

<a name="异步测试"></a>异步测试

项目中不仅仅用到上面那种简单测试,也会碰到接口测试这种需要时间的测试!因单元测试时串行的一个个函数执行,我们肯定不能让某个测试无限时的执行下去。下面我们用sleep来模拟接口请求。

    func testMyOne() {
          //设置失败原因
        var expecta:XCTestExpectation? = expectation(description: "expecta")
        
        let queue = DispatchQueue.global()
        queue.async {
            
            //网络请求
            sleep(2)
            
            //断言
            XCTAssertEqual("1", "1")
            
            //执行成功
            expecta?.fulfill()
            expecta = nil
        }
    
        //超时限制
        self.waitForExpectations(timeout: 1, handler: nil)
    }

执行以上的代码你会发现测试不通过
如下图


屏幕快照 2017-03-01 下午1.43.14.png

因sleep(2)了两秒,而超时的限制只有一秒,故在达到限制时间1s的时候expecta?.fulfill()这个成功标示还没执行到,就会报错。把timeout时间改大一点就可以通过测试。

要是把 expecta?.fulfill() 这行成功标示的代码放到sleep(2)的上面,则测试会通过。因在限制时间1s期限到时,expecta?.fulfill()已经得到执行,故判定为成功。如下图


屏幕快照 2017-03-01 下午1.49.36.png

<a name="通知测试"></a>通知测试

除了上面的异步方式,还可以用通知测试,如下面代码所示,sleep(2)超过了限制时间1S,测试将不通过。将限制时间改为>=2S即可通过测试。

func testMyTwo() {
        
        var expecta:XCTestExpectation? = expectation(description: "notification")
        
        //监听通知
        let noti = NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "notification"), object: nil, queue: nil) { (not) -> Void in
            DispatchQueue.global().async {
                //网络请求
                sleep(2)
                
                //断言
                XCTAssertEqual("1", "1")
                
                //测试成功
                expecta?.fulfill()
                expecta = nil
            }
        }
        
        //同步的写在这边,全局异步写 (1)和 (2)都没问题。  //(1)
        //self.waitForExpectations(timeout: 1,handler: nil)
        
        //发送通知
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "notification"), object: nil)
        
        //超时限制
        self.waitForExpectations(timeout: 1,handler: nil) //异步的写在这边也无所谓                       //(2)
        
        //删除通知
        NotificationCenter.default.removeObserver(noti)
    }

注意点:

  • 在执行不是并行异步的的sleep情况下,waitForExpectations 要在发送通知前,不然限制时间是不管用的,这涉及到多线程的知识,有兴趣的可以看我的另外一篇文章 GCD 细细的读

  • 在异步和通知模式时,是以在超时前能执行到fulfill() 判定成功

<a name="总结"></a>总结

会以上的这些知识,足够应对日常开发的单元测试了,欢迎讨论。

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

推荐阅读更多精彩内容