每个 iOS 程序员都要时不时的为他们的 APP 做 Debug。除非你是那种超级大牛,否则你肯定体验过查了无数个小时的 Bug 最后才发现那仅仅是个简单的语法错误时那种油然而生的绝望感。或者更糟:你根本就没发现那些 Bug。无论你是编程新手,还是开发过很多 APP 的老司机,例行的写写单元测试会让你的代码更可靠,更安全,更容易 Debug!
你很走运,Xcode 7 和 Swift 支持单元测试。尽管单元测试不保证(有了它你就会写出)绝对没有 Bug 的 APP,它还是一种能让你验证每段代码是否如期工作,并让 debug 过程更加便利。
正如其名,在单元测试中你要为某段代码单元创建一些小规模的、针对其某个特性的测试,然后确保每个代码单元都能通过这些测试。如果通过的话,它的旁边会出现一个绿色小标志,而如果因故测试不通过, Xcode 会把该测试标记为 “failed”。这就提示你去查看代码,找出失败原因。
这篇教程将简要介绍如何在 Swift 项目中使用XCTest.framework
进行代码单元测试。那么我们为什么需要做单元测试呢?单元测试对于我们有以下几点帮助:
帮助理解需求,单元测试应该反映 Use Case,把被测单元当成黑盒测试其外部行为。
提高实现质量,单元测试不保证程序做正确的事,但能帮助保证程序正确地做事,从而提高实现质量。
测试成本低,相比集成测试、验收测试,单元测试所依赖的外部环境少,自动化程度高,时间短,节约了测试成本。
反馈速度快,单元测试提供快速反馈,把 Bug 消灭在开发阶段,减少问题流到集成测试、验收测试和用户,降低了软件质量控制的成本。
利于重构,由于有单元测试作为回归测试用例,有助于预防在重构过程中引入 Bug。
文档作用,单元测试提供了被测单元的使用场景,起到了使用文档的作用。
对设计的反馈,一个模块很难进行单元测试通常是不良设计的信号,单元测试可以反过来指导设计出高内聚、低耦合的模块。
默认测试类
首先我们新建一个项目SwiftUnitTest
,它将在SwiftUnitTestTests
目录下自动创建出一个默认测试类(文件)SwiftUnitTestTests.swift
:
|
|
在这个文件中定义了一个测试类SwiftUnitTestTests
,它里面包含了一个setUp()
方法和tearDown()
方法,分别用来在每个测试方法运行之前做初始化准备,和在测试方法运行之后做清理工作。此外,它还包含了以test
开头命名的2个测试方法:testExample()
和testPerformanceExample()
。
我们需要注意:
- 任何以
test
开头命名的的方法都是一个测试方法,在每次单元测试执行时自动执行,它没有返回值; - 在测试方法中,可以使用
self.measureBlock() { }
来测量代码的运行时间; - 测试方法执行的顺序跟测试方法名有关,比如
test01()
会优先于test02()
执行
通过快捷键CMD+U
即可运行当前的单元测试。可以看到所有测试方法已通过。同样,使用CMD+SHIFT+Y
打开Console
也能看到相应测试方法的运行提示。
定制测试类
为了更好的管理测试用例,我们建议为某个需要测试的类单独创建一个测试类(文件),在这之前,我们先创建一个简单的类用来测试:
|
|
这个类定义了一种Person
类型,它有一个属性叫name
,其初始状态为Children。我们可以对其调用transform
方法,之后它就变成了GrownMan。
然后我们新建一个针对Person
类做测试的测试类:新建文件,选择Test Case Class
, 为此类取名为PersonTest
(建议使用<待测试类名>Tests
的形式):
然后我们删除原来的testExample
测试方法,并新建方法:
|
|
注意:如果此时Xcode提示无法找到
Person
的类定义,请在顶部加上@testable import SwiftUnitTest
。里面的SwiftUnitTest
是当前项目的名称。
在此测试方法中,我们创建出了一个新的Person
实例,然后对其调用transform()
方法。这时我们使用断言XCTAssert
来判断person
目前的name
属性值是否为GrownMan
。XCTAssert
是一个全局函数,它的第一个参数为布尔表达式,如果为true
表示断言通过;它的第二个参数为断言的描述。
注意:如果实例创建比较复杂,并且需要在多个测试方法中使用。你可以在类中定义对应的实例属性,并且在
setUp()
方法中进行初始化,在tearDown()
方法中进行资源清理。
运行单元测试
此时执行CMD+U
运行单元测试,可以看到单元测试都已通过:
然后我们再修改原有测试方法testPerformanceExample()
中的内容:
|
|
再次CMD+U
执行单元测试,等待几秒钟,可以看到所有测试用例都已通过,打开console
可以看到testPerformanceExample()
中代码的运行时间:
|
|
断言测试API列表
|
|