【譯】如何用Swift進行TDD(測試驅動開發)
本文由CocoaChina譯者 @ALEX吳浩文 翻譯
原文: How can you do TDD with Swift?
如果你還沒有用類似Swift的編譯型語言進行過TDD,你可能想問: 如果測試引用的對象不存在,你怎么進行代碼編譯,又怎么進行TDD呢?
相對于類似Swift的編譯型語言,類似Ruby和JavaScript的解釋型語言可能天生更適合TDD,因為你可以編寫不存在的測試對象,并且不會產生編譯錯誤。
所以該如何用編譯型語言進行TDD?
你可以直接編寫測試代碼,放任它編譯失敗。如果你把“編譯失敗”當作解釋型語言的測試失敗,就簡單多了。失敗就是失敗,無論是由于編譯器還是你的測試。
為了說明這一點,我們對Project類進行TDD,我們希望創建一個它的字典,這樣之后可以進行序列化。
1、創建一個測試和你想要存在的實例
因為我們想要測試的是創建一個Project的字典,我們需要一個Project的實例(當前它并不存在)。
class ProjectTests: XCTestCase { func test_asDictionary() { let project = Project(id: 5) } }
編譯失敗,所以測試失敗了。我們有一個好的開始,說真的,這就是TDD——我們希望我們的第一個測試是失敗的。
測試狀態:紅色。
2、編寫你想要存在的類
為了解決編譯錯誤,Project需要一個有id參數的init,代碼如下:
class Project { private let id: Intinit(id: Int) { self.id = id }
}</pre>
這修復了編譯錯誤,所以測試通過。
測試狀態:綠色。
3、在測試中,調用你想要存在的方法
現在我們想用Project實例調用asDictionary方法,這個方法將給我們Project的字典表示。
func test_asDictionary() { let project = Project(id: 5) let dict = project.asDictionary() }編譯失敗,所以測試狀態為紅色。好,我們可以繼續進行。
測試狀態:紅色。
4、編寫你想要存在的方法
在Project類里,我們現在可以實現asDictionary方法了,但是注意我們要用最簡短的代碼來通過測試。(換句話說,不要用的id屬性!)
func asDictionary() -> [String: AnyObject] { return [String: AnyObject]() }記住,在TDD過程中,我們總是試圖做最簡單的事情來通過測試。所以這里我們只返回一個空的字典——我們暫時不需要任何鍵或值,因為沒有失敗的測試告訴我們這樣做。
這使得測試狀態為綠色,因為它修復了編譯錯誤。當然,我們的測試還不告訴我們很多信息,所以我們需要寫一個斷言。
測試狀態:綠色。
5、在測試里,編寫一個斷言
現在我們可以在asDictionary方法的返回值里做斷言。我們希望Project的id出現在字典里。所以我們的測試變成了這樣:
func test_asDictionary() { let project = Project(id: 5) let dict = project.asDictionary()XCTAssertEqual(dict["id"] as? Int, 5)
}</pre>
這通過了編譯,但是運行的時候,測試失敗了,它告訴我們nil并不等于5。我們的測試再次失敗,但沒關系,我們可以修復它!
測試狀態:紅色。
6、實現方法,來通過測試
現在我們可以編寫方法邏輯,履行斷言,使測試通過。
回到我們的Project,我們可以更新asDictionary:
func asDictionary() -> [String: AnyObject] { return ["id": 5] }什么?你可能會想,現在我們不是應該返回id而不是5嗎?如果我們真的在實行TDD,那就不應該,我們不應該返回id屬性的值。返回硬編碼值5在這里是最簡單的通過測試的方法。如果我們想斷言返回的字典里有id,我們需要另一個測試。
測試狀態:綠色。斷言狀態:不夠好。
7、編寫另一個測試,下一個新的斷言
現在我們可以編寫一個完整的測試,并且沒有任何編譯錯誤。我們會創建一個新的測試,其中Project的id能給出除5以外的一個值,調用asDictionary,下斷言。
func test_asDictionary_with_id_7() { let project = Project(id: 7) let dict = project.asDictionary()XCTAssertEqual(dict["id"] as? Int, 7)
}</pre>
這將會編譯失敗,因為asDictionary的id值總是5。這很好,因為現在我們有一些不錯的斷言告訴我們代碼應該如何工作。
測試狀態:紅色。斷言狀態:好。
8、實現方法,使測試通過
現在我們可以更新asDictionary使我們的測試通過。但是這一次,返回一個硬編碼["id": 7]并沒有用,因為這將打破我們的第一個測試。我們可以修改這個方法來返回字典里的id值,像這樣:
func asDictionary() -> [String: AnyObject] { return ["id": id] }當我們運行測試,他們通過了!現在我們可以相信asDictionary將始終返回字典里的id。
測試狀態:綠色。斷言狀態:好。
結論
你 可以用類似Swift的編譯型語言實踐TDD——事實上, Test Driven Development: By Example(這本書繼續談了TDD)使用了Java這個編譯型語言來說明如何進行TDD。只要你以同樣的方式對待編譯錯誤和解釋型語言的測試失 敗,TDD過程是完全相同的。
進一步探索
你可以點這里 從GitHub獲取上面例子中的代碼 。
如果你想看這些在一個真正的工程里的運作,可以看這個 TDD重構視頻 。
原文 http://www.cocoachina.com/swift/20151112/14152.html