【译】如何用Swift进行TDD(测试驱动开发)
2015-11-18 06:00:17 | 来源:玩转帮会 | 投稿:佚名 | 编辑:小柯

原标题:【译】如何用Swift进行TDD(测试驱动开发)

本文由CocoaChina译者 @ALEX吴浩文 翻译

原文:How can you do TDD with Swift?

如果你还没有用类似Swift的编译型语言进行过TDD,你可能想问:如果测试引用的对象不存在,你怎么进行代码编译,又怎么进行TDD呢?

相对于类似Swift的编译型语言,类似Ruby和JavaScript的解释型语言可能天生更适合TDD,因为你可以编写不存在的测试对象,并且不会产生编译错误。

所以该如何用编译型语言进行TDD?

你可以直接编写测试代码,放任它编译失败。如果你把“编译失败”当作解释型语言的测试失败,就简单多了。失败就是失败,无论是由于编译器还是你的测试。

为了说明这一点,我们对Project类进行TDD,我们希望创建一个它的字典,这样之后可以进行序列化。

1、创建一个测试和你想要存在的实例

因为我们想要测试的是创建一个Project的字典,我们需要一个Project的实例(当前它并不存在)。

classProjectTests:XCTestCase{
functest_asDictionary(){
letproject=Project(id:5)
}
}

编译失败,所以测试失败了。我们有一个好的开始,说真的,这就是TDD——我们希望我们的第一个测试是失败的。

测试状态:红色。

2、编写你想要存在的类

为了解决编译错误,Project需要一个有id参数的init,代码如下:

classProject{
privateletid:Int
init(id:Int){
self.id=id
}
}

这修复了编译错误,所以测试通过。

测试状态:绿色。

3、在测试中,调用你想要存在的方法

现在我们想用Project实例调用asDictionary方法,这个方法将给我们Project的字典表示。

functest_asDictionary(){
letproject=Project(id:5)
letdict=project.asDictionary()
}

编译失败,所以测试状态为红色。好,我们可以继续进行。

测试状态:红色。

4、编写你想要存在的方法

在Project类里,我们现在可以实现asDictionary方法了,但是注意我们要用最简短的代码来通过测试。(换句话说,不要用的id属性!)

funcasDictionary()->[String:AnyObject]{
return[String:AnyObject]()
}

记住,在TDD过程中,我们总是试图做最简单的事情来通过测试。所以这里我们只返回一个空的字典——我们暂时不需要任何键或值,因为没有失败的测试告诉我们这样做。

这使得测试状态为绿色,因为它修复了编译错误。当然,我们的测试还不告诉我们很多信息,所以我们需要写一个断言。

测试状态:绿色。

5、在测试里,编写一个断言

现在我们可以在asDictionary方法的返回值里做断言。我们希望Project的id出现在字典里。所以我们的测试变成了这样:

functest_asDictionary(){
letproject=Project(id:5)
letdict=project.asDictionary()
XCTAssertEqual(dict["id"]as?Int,5)
}

这通过了编译,但是运行的时候,测试失败了,它告诉我们nil并不等于5。我们的测试再次失败,但没关系,我们可以修复它!

测试状态:红色。

6、实现方法,来通过测试

现在我们可以编写方法逻辑,履行断言,使测试通过。

回到我们的Project,我们可以更新asDictionary:

funcasDictionary()->[String:AnyObject]{
return["id":5]
}

什么?你可能会想,现在我们不是应该返回id而不是5吗?如果我们真的在实行TDD,那就不应该,我们不应该返回id属性的值。返回硬编码值5在这里是最简单的通过测试的方法。如果我们想断言返回的字典里有id,我们需要另一个测试。

测试状态:绿色。断言状态:不够好。

7、编写另一个测试,下一个新的断言

现在我们可以编写一个完整的测试,并且没有任何编译错误。我们会创建一个新的测试,其中Project的id能给出除5以外的一个值,调用asDictionary,下断言。

functest_asDictionary_with_id_7(){
letproject=Project(id:7)
letdict=project.asDictionary()
XCTAssertEqual(dict["id"]as?Int,7)
}

这将会编译失败,因为asDictionary的id值总是5。这很好,因为现在我们有一些不错的断言告诉我们代码应该如何工作。

测试状态:红色。断言状态:好。

8、实现方法,使测试通过

现在我们可以更新asDictionary使我们的测试通过。但是这一次,返回一个硬编码["id": 7]并没有用,因为这将打破我们的第一个测试。我们可以修改这个方法来返回字典里的id值,像这样:

funcasDictionary()->[String:AnyObject]{
return["id":id]
}

当我们运行测试,他们通过了!现在我们可以相信asDictionary将始终返回字典里的id。

测试状态:绿色。断言状态:好。

结论

你可以用类似Swift的编译型语言实践TDD——事实上, Test Driven Development: By Example(这本书继续谈了TDD)使用了Java这个编译型语言来说明如何进行TDD。只要你以同样的方式对待编译错误和解释型语言的测试失败,TDD过程是完全相同的。

进一步探索

你可以点这里从GitHub获取上面例子中的代码。

如果你想看这些在一个真正的工程里的运作,可以看这个TDD重构预告片。

tags:

上一篇  下一篇

相关:

我已经写了48年代码了,我感觉我还能写下去

这是来自quroa的问题:Why-aren’t-there-a-lot-of-old-programmers-at-software-companies下的一个回答。很

Android端10个最常见问题

这里逐条记录下最容易遇到的 React native android 相关case1.app启动后,红色界面,unable load jsbundle解

Android热更新实现原理及代码分析

最近Android社区的氛围很不错嘛,连续放出一系列的Android动态加载插件和热更新库,这篇文章就来介绍一下An

MySQL高可用性之Keepalived双主热备

转载补充:通常说的「双机热备」是指两台机器都在运行,但并不是两台机器都同时在提供服务。当提供服务的一

17大Python奇技淫巧

显示有限的接口到外部当发布python第三方package时,并不希望代码中所有的函数或者class可以被外部import,

D、GO、Rust谁会在未来取代C?为什么?

不要管我的地位和 D 语言创造者之一的身份。我会坦诚的回答这个问题。我熟悉 Go 和 Rust,并且知道 D 的缺点

一个简单易用的Android导航栏TitleBar

一个简单易用的导航栏TitleBar,可以轻松实现IOS导航栏的各种效果整个代码全部集中在TitleBar.java中,所有

舒缓工作压力 塑造健康心理

为进一步缓解干警工作压力,提高干警心理健康水平。今日,我监特邀贵州省心理工作协会理事周敏老师到

关于印发《商务行业2015至2016年度预防煤气中毒工作方案》的通知

各区(县)商务委、开发区商务局,市餐饮行业协会,市商务执法监察大队,各有关单位: 现将《商务行业2015

关于做好未通过2014年度重点流域考核地区后续整改工作的通知

文件名称:关于做好未通过2014年度重点流域考核地区后续整改工作的通知文件编号:环办函[2015]1834号发布时间

站长推荐: