代碼更加容易被理解 單元測試的好處通常并非是人們最初所期待的,在一個(gè)工程中考慮修改一些你之前從沒有看過的代碼(比方說,一個(gè)特殊的類或者方法).你將如何動(dòng)手處理這些代碼?你可能需要在項(xiàng)目中去瀏覽這些特定的類或者方法使用的代碼,理所當(dāng)然,單元測試就是這樣例子的一個(gè)很好的場所。同時(shí),當(dāng)正確寫入的時(shí)候,單元測試可以為工程提供一個(gè)API文件的容易讀取的設(shè)置,使得文檔的處理和代碼的理解對(duì)于整個(gè)團(tuán)隊(duì)中的新老開發(fā)者一樣的簡單,便捷。然而,這些只能在測試是易讀的和容易理解的情況下才能被確認(rèn),這個(gè)規(guī)則很多的單元測試開發(fā)者并不會(huì)遵循。我將詳述這個(gè)信任,然后在這篇文章的易讀測試的部分給你展現(xiàn)如何在去寫易讀的單元測試。
測試正確的事情
新來者在Test Driven Development (TDD)中一個(gè)最通常的錯(cuò)誤就是他們通常會(huì)搞混"Fail by testing something illogical."中的"Fail first"要求。例如,你可以用下面的規(guī)格開始這個(gè)方法: ' returns the sum of the two numbers
Function Sum(ByVal a As Integer, ByVal b As Integer) As Integer
你可以向如下的方式寫一個(gè)失敗測試: <TestMethod()> _
Public Sub Sum_AddsOneAndTwo()
Dim result As Integer = Sum(1, 2)
Assert.AreEqual(4, result, "bad sum");
End Sub
初看上去這個(gè)處理像是一個(gè)寫失敗測試的好的方法,它完全錯(cuò)失了你寫錯(cuò)誤測試的初始點(diǎn)。
一個(gè)失敗測試驗(yàn)證了在代碼中存在一些錯(cuò)誤,當(dāng)你的測試完成后這個(gè)測試應(yīng)該是通過的,現(xiàn)在的例子中,無論如何,測試都將會(huì)失敗,即使是代碼完成,因?yàn)闇y試邏輯上不是正確的。如果希望測試通過測需要測試自身進(jìn)行修改――而不是程序的代碼的改變(當(dāng)程序代碼改變的時(shí)候,是test-first規(guī)劃的意圖)簡短來說,這個(gè)測試不會(huì)反映出程序代碼完成后的最終的結(jié)果,因此這個(gè)不是一個(gè)好的測試。 單元測試小技巧[2]http://www.csai.cn 作者:Roy Osherove 來源:MSND 2007年1月24日
TDD中一個(gè)好的測試要求你去修改代碼,從而使它能夠按照想要的方式工作,這一點(diǎn)要?jiǎng)儆趶?qiáng)迫你去反映現(xiàn)在的真實(shí)情況或者一個(gè)非邏輯要求的渴望的結(jié)果。例如,當(dāng)1+1返回0時(shí)就意味著測試失敗。這個(gè)簡單的例子和這種情況是相似的,在練習(xí)中,如果現(xiàn)在的需求是在工作的,測試應(yīng)該可以反映你所期待的結(jié)果,然后你可以調(diào)整現(xiàn)在代碼的情況去通過這個(gè)測試。
作為一個(gè)規(guī)則,一個(gè)已經(jīng)調(diào)通的測試不應(yīng)該被移除掉,因?yàn)檫@個(gè)測試在維護(hù)工作中可以用于恢復(fù)測試。他們在你改變代碼時(shí)用來確定你沒有損害到現(xiàn)在已經(jīng)工作的函數(shù)。這就是為什么你不應(yīng)該修改那些已經(jīng)通過的測試,除非是一些很小的修改,例如增加它的可讀性(換句話說,分解測試)
當(dāng)一個(gè)測試非正常失敗 有時(shí)你可能遇到失敗的測試,而這時(shí)你對(duì)代碼的改變是完全合理的。這通常是因?yàn)槟阌龅搅藳_突的需求。一般來說,可能是一個(gè)新的需求(一個(gè)改變的特性)與一個(gè)舊的可能已經(jīng)不再有效的需求發(fā)生了沖突。這有兩種可能:
1. 在舊的需求或者無效或者在別處測試的情況下刪除被驗(yàn)證本質(zhì)上不再有效的失敗的測試
2. 改變舊的測試使你可以測試新的要求(本質(zhì)上使用新的測試),然后在新的設(shè)置下(測試的邏輯狀態(tài)相同,但是初始功能函數(shù)可能有所不同)測試舊的需求。
而有時(shí)候一個(gè)測試在使用不完整的技術(shù)去完成任務(wù)的時(shí)候也是有效的,例如,你有一個(gè)成員類帶有一個(gè)FOO方法,它表現(xiàn)為某幾種行為,它已經(jīng)經(jīng)由Test在X年前測試完成,然后現(xiàn)在一些其他的需求加了進(jìn)來,方法的邏輯增強(qiáng)了,從而可以去處理一些類似于在獲取數(shù)據(jù)時(shí)丟失一些參數(shù)的異常處理。但這時(shí),突然Test X失敗了,雖然在測試這個(gè)函數(shù)的時(shí)候只是使用了同樣的類。這個(gè)測試的失敗是因?yàn)樵谡{(diào)用方法之前丟失了一些初始處理步驟。
這并不意味著你需要移除Test X,你將丟失對(duì)于一些重要功能的測試,這時(shí)你應(yīng)該去關(guān)心那些初始化時(shí)的問題,而不是改變類的創(chuàng)建以用來適應(yīng)你新的意圖。
當(dāng)然如果你那里有200個(gè)測試都是因?yàn)榕f的結(jié)構(gòu)導(dǎo)致的失敗,你就應(yīng)該找到這個(gè)問題來維護(hù)你的測試。這就是為什么你應(yīng)該總是移除你測試中的副本尤其是在生產(chǎn)代碼中。
測試覆蓋和測試Angles 你如何知道是否你的新代碼是一個(gè)好的覆蓋?當(dāng)試圖移動(dòng)一個(gè)鏈接或者一個(gè)約束檢查后,如果所有的測試依然通過,那么你就沒有足夠的代碼復(fù)制然后你可能需要添加其他的測試單元。
確認(rèn)你添加正確測試的最好方法就是測試一些最平常的行和檢查直到用非常的手段使它出錯(cuò)。這個(gè)也許很難,但是如果你不能考慮出一個(gè)讓代碼出錯(cuò)的方法,你就可能沒有好的理由在最初的地方寫下這行代碼。
更多軟考資料請?jiān)L問:考試吧軟件水平考試欄目
希望與更多網(wǎng)友交流,請進(jìn)入考試吧軟件水平考試論壇
北京 | 天津 | 上海 | 江蘇 | 山東 |
安徽 | 浙江 | 江西 | 福建 | 深圳 |
廣東 | 河北 | 湖南 | 廣西 | 河南 |
海南 | 湖北 | 四川 | 重慶 | 云南 |
貴州 | 西藏 | 新疆 | 陜西 | 山西 |
寧夏 | 甘肅 | 青海 | 遼寧 | 吉林 |
黑龍江 | 內(nèi)蒙古 |