单元测试

目录

  • 前言
  • 断言语法
  • 配置
  • 添加测试
  • 异步测试
  • 通知测试
  • 总结

前言

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

断言语法

单元测试的关键点在于 "断言"。在"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 直接测试失败 不通过

配置

在测试文件中有两个初始的方法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()
    }

添加测试

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

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

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


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

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


单元测试_第1张图片
屏幕快照 2017-03-01 下午1.16.22.png

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

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


单元测试_第3张图片
屏幕快照 2017-03-01 下午1.23.58.png

异步测试

项目中不仅仅用到上面那种简单测试,也会碰到接口测试这种需要时间的测试!因单元测试时串行的一个个函数执行,我们肯定不能让某个测试无限时的执行下去。下面我们用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)
    }

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


单元测试_第4张图片
屏幕快照 2017-03-01 下午1.43.14.png

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

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


单元测试_第5张图片
屏幕快照 2017-03-01 下午1.49.36.png

通知测试

除了上面的异步方式,还可以用通知测试,如下面代码所示,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() 判定成功

总结

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

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