總是以為自己了解了測試驅動開發,其實做起來和了解根本不是一回事。原來覺得代碼清晰得很,後來試驗了一下才知道那是自己的錯覺。這次,讓我們拋卻Eclipse的自動補全功能,來一場真正的測試驅動開發吧。
項目描述:這是一個很簡單的項目,目標是掃描磁盤上所有特定格式的文件,將其路徑存儲下來,通過程序可以快捷搜索到文件路徑並自動定位到該文件。
用戶故事(簡單點寫了):
1、 掃描磁盤,將目錄下的所有文件列出來,將特定格式的文件信息存儲到磁盤。
2、 所有文件的信息可以被查詢。
3、 被查詢出的信息可以雙擊打開所在文件夾並定位該文件。
好了,這就是第一次的迭代目標,其中文件的格式枚舉,存儲到磁盤的形式,都可以以後再說,那麼針對於故事的過程,我們開始設計並寫測試吧:
設計:
1、 平面文件存儲,每個文件以行為單位存儲,不同屬性以###分割,實例化到FileInfo類(故事1)。
2、 平面文件叫fileDB。文件以行讀取到List,以帶格式的String寫入(故事1)。
3、 特定文件格式以正則表達式匹配(故事1)。
4、 查詢的條件是文件名,通過遍歷List查找屬性是否符合contains規則(故事2)。
5、 用JNI explorer打開並定位文件(故事3)。
建立測試:
這裡首先關注的是設計中的第一條。
新建一個Junit Test Case,我將測試的類叫FileInfo,所以這個測試類叫FileInfoTest,它與FileInfo在同一包路徑下,但是在不同的resource folder下。
這個Test Case應該不能通過測試。
事實證明,它的確無法通過測試
然後,它應該這樣被初始化。
編譯錯誤!那當然,因為類FileInfo還不存在,讓我們建立它。
編譯通過了,我們需要它將字段輸出成一個帶###分隔符的字符串,字符串的組成是FileName###FileDir###FilePath###LastUpdate。
那麼測試應該變成這樣了:
為了解決這些紅槓,FileInfo得變成這樣。
(這裡有那麼一點點牽強,就是get方法和成員變量的來源不是“剛剛好通過測試”,而是測試原本是為了引出成員變量)
現在toString應該變成這樣:a.txt###c:\\###c:\\a.txt###2016-01-01。
所以測試應該變成這樣(這樣寫代碼好費時間!但參與設計的過程也相應變多,思考和工作量都在增長)
當然,測試失敗了,二者並不相等
原因當然在toString
修改FileInfo的toString方法:
測試通過了!
此時,我在想,如果因為某種原因,我想將###換成@@@,那麼toString方法中###應該以變量的形式出現。但因為此次將修改的代碼對通過測試沒有任何意義,也不能增加功能,所以我不這麼做。我會在什麼時候這樣做呢?我會等到代碼的功能很多,我重構它並能展示此時測試對我重構的意義的時候。
現在我們完成了設計1,來開始設計2吧。(未完……)