XCTest iOS Swift单元测试

iOS XCTest单元格测试

XCTest iOS7的时候就接触了,可是一直也没用起来。起初的我觉得单元格测试纯属鸡肋,我们只能测试单个类的一个函数,还要自己判断期望的结果,进行验证。如果依赖关系复杂,那么就GG了。

成长是什么呢,成长是在不同阶段看待一个事物不同的看法。现在iOS 11了,从新再看到XCTest和新出的XCUITest,已不是当年的一脸嫌弃和不屑了。

记住一句话存在即合理。下面就是我从新花了1天时间学习路线(点开是链接地址):

  • WWDC XCTest
  • WWDC XCUITest
  • GITHUB Demo
  • OCMock
  • [iOS单元测试系列]单元测试框架选型

认识 XCTest

新建项目的时候,Xcode都会问我们是否新建XCUnitTest和XCUITest。那么XCUnitTest是干什么的呢,怎么用呢,都包括什么呢。

新建项目的Tests Target 文件是这样的:

import XCTest
@testable import XCTestDemo

class XCTestDemoTests: XCTestCase {

    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()
    }

    func testExample() {
        // This is an example of a functional test case.
        // Use XCTAssert and related functions to verify your tests produce the correct results.
    }

    func testPerformanceExample() {
        // This is an example of a performance test case.
        self.measure {
            // Put the code you want to measure the time of here.
        }
    }

}

从注释我们可以知道这四个函数的意思:

函数

用途

setUp

继承与XCTestCase 函数测试文件开始执行的时候运行

tearDown

继承与XCTestCase 测试函数运行完之后执行

testExample

测试的例子函数

testPerformanceExample

性能测试

下面XCTest 使用简单的例子

看了应该明白怎么用了

//
//  XCTestDemoTests.swift
//  XCTestDemoTests
//
//  Created by Nvr on 2018/7/6.
//  Copyright © 2018年 ZY. All rights reserved.
//

import XCTest
@testable import XCTestDemo

class XCTestDemoTests: XCTestCase {

    var f1:Float?
    var f2:Float?

    override func setUp() {
        super.setUp()
        // Put setup code here. This method is called before the invocation of each test method in the class.
        f1 = 10.0
        f2 = 20.0
    }

    override func tearDown() {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
        super.tearDown()
    }

    func testExample() {
        // This is an example of a functional test case.
        // Use XCTAssert and related functions to verify your tests produce the correct results.
        XCTAssertTrue(f1! + f2! == 30.0)
    }

    //simpale Test
    func testIsPrimenumber()  {
        let oddNumber = 5
        //There are lot XCTAssert function, you can check it
        XCTAssertTrue(isPrimenumber(number: Double(oddNumber)))
    }

    func isPrimenumber(number:Double) -> Bool{
        for No in 1...Int(sqrt(number)) {
            if Int(number)/No != 0 {
                return true
            }
        }
        return false
    }

    func testPerformanceExample() {
        // This is an example of a performance test case.
        self.measure {
            // Put the code you want to measure the time of here.
        }
    }

}

例子说明:

函数

说明

testExample

全局变量f1 + f2 相加是否等于固定的数,断言是否相等

testIsPrimenumber

判断是否是素数 断言是否返回真

总结:通过上面的两个例子,应该明白了XCUintTest是干什么,怎么用的啦。

断言常用API:

API

说明

XCTFail(…)

任何尝试都会测试失败,…是输出的提示文字。(后面都是这样)

XCTAssertNil(expression, …)

expression为空时通过,否则测试失败。 expression接受id类型的参数。

XCTAssertNotNil(expression, …)

expression不为空时通过,否则测试失败。expression接受id类型的参数。

XCTAssert(expression, …)

expression为true时通过,否则测试失败。expression接受boolean类型的参数。

XCTAssertTrue(expression, …)

expression为true时通过,否则测试失败。expression接受boolean类型的参数。

XCTAssertFalse(expression, …)

expression为false时通过,否则测试失败。expression接受boolean类型的参数。

XCTAssertEqualObjects(expression1, expression2, …)

expression1和expression1地址相同时通过,否则测试失败。expression接受id类型的参数。

XCTAssertNotEqualObjects(expression1, expression2, …)

expression1和expression1地址相同时通过,否则测试失败。expression接受id类型的参数。

XCTAssertEqual(expression1, expression2, …)

expression1和expression1相等时通过,否则测试失败。expression接受基本类型的参数(数值、结构体之类的)。

XCTAssertNotEqual(expression1, expression2, …)

expression1和expression1不相等时通过,否则测试失败。expression接受基本类型的参数。

XCTAssertEqualWithAccuracy(expression1, expression2, accuracy, …)

expression1和expression2之间的任何值都大于accuracy时,测试失败。expression1、expression2、accuracy都为基本类型。

XCTAssertNotEqualWithAccuracy(expression1, expression2, accuracy, …)

expression1和expression2之间的任何值都小于等于accuracy时,测试失败。expression1、expression2、accuracy都为基本类型。

XCTAssertGreaterThan(expression1, expression2, …)

expression1 <= expression2时,测试失败。expression为基本类型

XCTAssertGreaterThanOrEqual(expression1, expression2, …)

expression1 < expression2时,测试失败。expression为基本类型

XCTAssertLessThan(expression1, expression2, …)

expression1 >= expression2时,测试失败。 expression为基本类型

XCTAssertLessThanOrEqual(expression1, expression2, …)

expression1 > expression2时,测试失败。 expression为基本类型

XCTAssertThrows(expression, …)

expression没抛异常,测试失败。expression为一个表达式

XCTAssertThrowsSpecific(expression, exception_class, …)

expression没抛指定类的异常,测试失败。expression为一个表达式,exception_class为一个指定类

XCTAssertThrowsSpecificNamed(expression, exception_class, exception_name, …)

expression没抛指定类、指定名字的异常,测试失败。expression为一个表达式exception_class为一个指定类,exception_name为一个指定名字

XCTAssertNoThrow(expression, …)

expression抛出异常时,测试失败。expression为一个表达式

XCTAssertNoThrowSpecific(expression, exception_class, …)

expression抛出指定类的异常,测试失败。expression为一个表达式

XCTAssertNoThrowSpecificNamed(expression, exception_class, exception_name, …)

expression抛出指定类、指定名字的异常,测试失败。


异步测试

下面一些情况会用到异步测试:

  • 打开文档
  • 在其他线程工作
  • 和服务或者扩展进行交流
  • 网络活动
  • 动画
  • UI测试的一些条件

网络请求异步Case

关于UI的异步测试在下篇XCUITest中说,一个网络请求的Case可以说明白异步测试的机制。

  1. pod导入alamofire,Target是你要测试的tests Target.
  2. 新建期望,用alamofire 发起请求。
  3. 请求回调里断言是否为空,fullfill期望看是否满足期望
  4. XCWaiter设置期望完成的时间
func testAsynNetworkTest(){

        let networkExpection = expectation(description: "networkDownSuccess")

        Alamofire.request("http://www.httpbin.org/get?key=Xctest", method: .get, parameters: nil, encoding: JSONEncoding.default).responseJSON { (respons) in
            XCTAssertNotNil(respons)
            networkExpection.fulfill()
        }


//        waitForExpectations(timeout: 0.00000001)
//        wait(for: [networkExpection], timeout: 0.00000001)


//XCTWaiter.Result  枚举类型如下
//        public enum Result : Int {
//
//
//            case completed
//
//            case timedOut
//
//            case incorrectOrder
//
//            case invertedFulfillment
//
//            case interrupted
//        }
        let result = XCTWaiter(delegate: self).wait(for: [networkExpection], timeout:  1)
        if result == .timedOut {
            print("超时")
        }
    }

说明:下面三个函数都是设置XCWaiter等待期望时间,只是细节不同。

函数

waitForExpectations(timeout: 0.00000001)

wait(for: [networkExpection], timeout: 0.00000001)

let result = XCTWaiter(delegate: self).wait(for: [networkExpection], timeout: 0.00000001)


Mock

重点来了,我一直

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励