Nimble 从字面上看是 敏捷,灵活 的意思。Nimble 是一个库,一个 断言库。这个库一般用于单元测试。Xcode 6 为我们集成了 XCTest 单元测试库。在正式介绍 Nimble 之前,我们有必要先介绍一下 XCTest。我们在使用 Xcode 新建项目的时候会发现它为我们创建了两个 Target,一个是我们项目的 Target 还有一个是测试 Target。

  我们看到了 Xcode 为我们自动生成的 Target,我们按下 Command + U 即可运行测试项目,并且在 Xcode 的左边会显示测试结果:

  让我们看看测试项目中的代码, MyTestTests.swift:
import UIKit
import XCTest
class MyTestTests: 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.
XCTAssert(true, "Pass")
}
func testPerformanceExample() {
// This is an example of a performance test case.
self.measureBlock() {
// Put the code you want to measure the time of here.
}
}
}
  这是测试项目中的一个类,它继承自 XCTestCase,并且里面实现了四个方法。其中以 test 开头的两个方法 testExample 和 testPerformanceExample 是具体的测试用例方法。我们看到 testExample 方法里面调用了一个 XCTAssert(true, "Pass") 方法。这个方法叫做断言方法,也是单元测试的核心。对于 XCAssert 方法,只有第一个参数为 true 的时候,测试用例才会通过。比如我们把这个方法改成这样:
  func testExample() {
  // This is an example of a functional test case.
  var i = 1;
  XCTAssert(i == 0, "variable i shoule be zero.")
  }
  我们在断言中判断变量 i 应该等于0,但我们实际给 i 赋值为 1。这时候我们再按 Command + U 来运行测试,这次我们的测试没有通过,因为断言失败了:

  我们看到,Xcode 将 XCAssert 的第二个参数用作错误提示显示了出来。这个例子说明了断言在单元测试中的作用。
  既然 XCTest 已经提供了像 XCAssert 这样的断言方法,我们为什么还需要用 Nimble 呢? 简单来说,XCTest 虽然提供了一系列的断言方法,但并不全面,比如它无法判断字符串包含关系,集合对象是否包含一个子集,以及测试异步方法的返回值。
  Nimble 解决了这个问题,它弥补了 XCTest 的上述缺陷。并且还更加和 BDD(一种叫做行为驱动开发的测试模式) 贴合。
  下面我们来看看如何用 Nimble 来表达上面的断言逻辑。
  首先我们将 Nimble 库添加到项目中,并将 .xcodeproj 文件放到项目结构中:

  然后我们把 Nimble-iOS 作为测试 Target 的依赖库添加进来:

  然后我们再修改 testExample 方法:
  func testExample() {
  var i = 1;
  expect(i).to(equal(0))
  }
  我们看到,我们将断言方式改为 expect(i).to(equal(0))。顺便说句题外话~,这样感觉是不是更加符合自然语言的逻辑,更贴近人性呢?XCTAssert(i == 0, "variable i shoule be zero.") 给人的感觉只是一个函数调用,而 expect(i).to(equal(0)) 仿佛是在说一句话一样,翻译成中文是:“期望变量 i 等于 0 ”。