单元测试
https://onevcat.com/2014/05/kiwi-mock-stub-test/ http://www.jianshu.com/p/b549fadc0f0c http://blog.csdn.net/hello_hwc/article/details/60957515
单元测试之前
对于iOS开发来说,良好的代码设计,是实行单元测试的前提。是吗???
WWDC中的视频和demo
engineering_for_testability,很有启发。
objc.io 的三篇文章:
- 把 Data Source 和其他 Protocols 分离出来。比如:UITableViewDataSource抽出来,代码移到单独的类ArrayDataSource。
- 将业务逻辑移到 Model 中。比如一些数据的处理。
- 有些代码不能被轻松地移动到 model 对象中,创建单独的类。
- 不要在 view controller 中做网络请求的逻辑。
- 把 View 代码移到 View 层,即通过封装新的view实现,而不是代码全写在ViewController。
- 将UITableViewController作为 child view controller 添加到其他 view controller 中,感觉不会好用。
- 分离关注点:
2.1. 通过cell的category来装配数据;
2.2. 多种 model 对象需要用同一类型的 cell 来表示,让 Cells 可复用,即给 cell 定义一个 protocol,需要用这个 cell 显示的对象必须遵循这个 protocol。然后简单修改 category 中的设置方法,让它可以接受遵循这个 protocol 的任何对象。这些简单的步骤让 cell 和任何特殊的 model 对象之间得以解耦,让它可适应不同的数据类型;
2.3. 在 Cell 内部控制 Cell 的状态,比如高亮;
- 控制多个 Cell 类型,在 Data Source 做分发;
- 编辑 Table View,修改数据很明显是属于 model 层的任务。Model 应该为诸如删除或重新排序等操作暴露一个 API,然后我们可以在 data source 方法中调用它。
- 查看代码,里面演示了如何测试Model,DataSource,ViewController。
MOCK & STUB
14年,在objc中,现在比较流行的BDD框架有cedar,specta和Kiwi。 现在,Quick的star数是7000多
BDD: 一个典型的BDD的测试用例包活完整的三段式上下文,测试大多可以翻译为Given..When..Then
的格式
STUB: 我们人为地来指定计算的结果,然后测试数据库的写入操作。人为地让一个对象对某个方法返回我们事先规定好的值,这就叫做 stub
MOCK: mock
其实就是一个对象,它是对现有类的行为一种模拟(或是对现有接口实现的模拟), mock
与 stub
最大的区别在于 stub
只是简单的方法替换,而不涉及新的对象,被 stub
的对象可以是业务代码中真正的对象。而 mock
行为本身产生新的(不可能在业务代码中出现的)对象,并遵循类的定义相应某些方法
Quick
// Swift
import Quick
import Nimble
class TableOfContentsSpec: QuickSpec {
override func spec() {
describe("the 'Documentation' directory") {
it("has everything you need to get started") {
let sections = Directory("Documentation").sections
expect(sections).to(contain("Organized Tests with Quick Examples and Example Groups"))
expect(sections).to(contain("Installing Quick"))
}
context("if it doesn't have what you're looking for") {
it("needs to be updated") {
let you = You(awesome: true)
expect{you.submittedAnIssue}.toEventually(beTruthy())
}
}
}
}
}
参考Quick的中文文档,知识点太多了主要有
使用明确清晰的方法名字
-func testPeel() { +func testPeel_makesTheBananaEdible() {
Arrange, Act, and Assert 三部曲
Arrange - 安排好所有先要条件和输入 Act - 对要测试的对象或方法进行演绎 Assert - 作出预测结果的断言
对条件进行测试
每个条件都进行测试
用 XCTestCase.setUp() 来编写更简洁的 “Arrange”
别测试代码,而应该验证程序的行为
比如测试数据库保存操作,不应该存储之后检查记录数是否加1,而应该检查存储后能否顺利取出
编写行为测试的关键,就在于思考这些问题:
这段程序代码是用来做什么的? 我的测试只验证了程序的行为吗?它可能因为代码运行的其他原因而不通过吗?
如何触发 UIViewController 生命周期事件,如何触发 UIControl 事件(如:点击按钮)
Quick 使用mock
Quick 使用 Shared Assertion 来复用测试模板代码
在某种场合下,一些特定的测试代码可以应用在不同的对象上。
比如,假设有一个叫 Edible 的协议。当一只海豚吃了标识为 Edible 的食物时,它会变得高兴。Mackerel 和 Cod 都遵循 Edible 协议。这个时候,Quick 的 shared example(共享用例)能帮你更容易地测试 Mackerel 和 Cod 的行为。