測試驅動開發 TDD

Test-driven development 測試驅動開發

測試驅動開發(TDD)是一個依賴於非常短的開發週期重複的軟件開發過程:需求變成非常具體的測試用例,然後軟件被改進以僅通過新測試。這與軟件開發相反,軟件開發允許添加未經證明符合要求的軟件。
美國軟件工程師肯特·貝克,誰相信被開發或“重新發現” [1]的技術,在2003年即TDD鼓勵簡單的設計和十足信心說。[2]
測試驅動開發與極端編程的測試優先編程概念有關,始於1999年,[3]但最近已經創造了更多的一般興趣。[4]
程序員還將該概念應用於改進和調試 使用舊技術開發的遺留代碼。[5]

1 測試驅動的開發週期

1.添加測試
在測試驅動開發中,每個新功能都從編寫測試開始。編寫一個定義功能或功能改進的測試,應該非常簡潔。要編寫測試,開發人員必須清楚地瞭解該功能的規範和要求。開發人員可以通過用例和用戶故事來完成此任務,以涵蓋需求和異常條件,並可以在適合軟件環境的任何測試框架中編寫測試。它可以是現有測試的修改版本。在編寫代碼之後,這是測試驅動開發與編寫單元測試的區別特徵:它使開發人員專注於之前的需求 編寫代碼,一個微妙但重要的區別。
2.運行所有測試並查看新測試是否失敗
這驗證了測試工具正常工作,表明新測試沒有通過而不需要新代碼,因爲所需的行爲已經存在,並且它排除了新測試存在缺陷並且總是通過的可能性。新測試應該因預期原因而失敗。此步驟增加了開發人員對新測試的信心。
3.編寫代碼
下一步是編寫一些導致測試通過的代碼。在這個階段編寫的新代碼並不完美,例如,可能會以不雅的方式通過測試。這是可以接受的,因爲它將在第5步中得到改進和磨練。
此時,編寫代碼的唯一目的是通過測試。程序員不得編寫超出測試檢查功能的代碼。
4.運行測試
如果現在所有測試用例都通過,程序員可以確信新代碼符合測試要求,並且不會破壞或降低任何現有功能。如果他們不這樣做,必須調整新代碼,直到他們這樣做。
5.重構代碼
在測試驅動的開發過程中,必須定期清理不斷增長的代碼庫。新代碼可以從方便傳遞測試的地方移動到更符合邏輯的地方。必須刪除重複。對象,類,模塊,變量和方法名稱應清楚地表示其當前的用途和用途,因爲添加了額外的功能。隨着功能的添加,方法體可以變長,其他對象變大。他們受益於分裂和他們的部分仔細命名,以提高可讀性和可維護性,這將在以後的日益有價值軟件生命週期。可以重新佈置繼承層次結構以使其更具邏輯性和幫助性,並且可能從公認的設計模式中受益。重構和創建乾淨代碼有特定的和一般的指導原則。[6] [7]通過在每個重構階段不斷重新運行測試用例,開發人員可以確信進程不會改變任何現有功能。
刪除重複的概念是任何軟件設計的重要方面。但是,在這種情況下,它也適用於刪除測試代碼和生產代碼之間的任何重複 - 例如在兩者中重複的幻數或字符串,以使測試在步驟3中通過。
從另一個新測試開始,然後重複該循環以推進該功能。步驟的大小應始終很小,每次測試運行之間只需編輯1到10次。如果新代碼沒有快速滿足新測試,或者其他測試意外失敗,程序員應該優先撤消或恢復過度調試。持續集成有助於提供可恢復的檢查點。當使用外部庫時,重要的是不要增加小到僅僅有效地測試庫本身的增量,[4]除非有理由相信庫有錯誤或功能不完整以便爲所有庫提供服務正在開發的軟件的需求。

2 發展風格

使用測試驅動開發有很多方面,例如“保持簡單,愚蠢”(KISS)和“ 你不需要它 ”的原則(YAGNI)。通過專注於僅編寫通過測試所需的代碼,設計通常比其他方法更清晰,更清晰。[2]在試驗驅動開發實例中,肯特貝克還提出了“ 僞造直到你製造它 ” 的原則。
爲了實現一些先進的設計概念,例如設計模式,編寫了生成該設計的測試。代碼可能仍然比目標模式更簡單,但仍然通過了所有必需的測試。這一開始可能令人不安,但它允許開發人員只關注重要的事情。
首先編寫測試:測試應該在要測試的功能之前編寫。據稱這有許多好處。它有助於確保編寫應用程序以實現可測試性,因爲開發人員必須考慮如何從一開始就測試應用程序,而不是稍後添加它。它還確保編寫每個功能的測試。此外,首先編寫測試可以更深入,更早地瞭解產品需求,確保測試代碼的有效性,並始終關注軟件質量。[8]在編寫特性優先代碼時,開發人員和組織傾向於將開發人員推向下一個功能,甚至完全忽略測試。第一個TDD測試可能最初甚至可能不編譯,因爲它所需的類和方法可能尚不存在。然而,第一個測試用作可執行規範的開頭。[9]
每個測試用例最初失敗:這確保測試真正起作用並且可以捕獲錯誤。一旦顯示,就可以實現底層功能。這導致了“測試驅動的開發咒語”,即“紅色/綠色/重構”,其中紅色表示失敗,綠色表示通過。測試驅動開發不斷重複添加失敗,傳遞和重構的測試用例的步驟。在每個階段接收預期的測試結果可以加強開發人員對代碼的心智模型,增強信心並提高生產力。
保持單位小

對於TDD,單元通常被定義爲一個類,或一組通常稱爲模塊的相關函數。聲稱保持相對較小的單位可提供重要的好處,包括:

減少調試工作量 - 檢測到測試失敗時,使用較小的單元有助於跟蹤錯誤。
自我記錄測試 - 小型測試用例更易於閱讀和理解。[8]

測試驅動開發的高級實踐可以導致驗收測試驅動開發(ATDD)和示例規範,其中客戶指定的標準自動進入驗收測試,然後驅動傳統的單元測試驅動開發(UTDD)過程。[10]此過程確保客戶擁有自動機制來確定軟件是否滿足其要求。通過ATDD,開發團隊現在有一個特定的目標 - 驗收測試 - 使他們不斷關注客戶真正想要的每個用戶故事。

3 最佳實踐

3.1 測試結構

測試用例的有效佈局可確保完成所有必需的操作,提高測試用例的可讀性,並平滑執行流程。一致的結構有助於構建自我記錄的測試用例。
測試用例的常用結構包括(1)設置,(2)執行,(3)驗證和(4)清理。

設置:將待測單元(UUT)或整個測試系統置於運行測試所需的狀態。
執行:觸發/驅動UUT以執行目標行爲並捕獲所有輸出,例如返回值和輸出參數。這一步通常很簡單。
驗證:確保測試結果正確。這些結果可能包括執行期間捕獲的顯式輸出或UUT中的狀態更改。
清理:將UUT或整個測試系統恢復到測試前狀態。此恢復允許在此之後立即執行另一個測試。

3.2 個人最佳實踐

個人可以遵循的一些最佳實踐是將常見的設置和拆卸邏輯分離爲適當的測試用例所使用的測試支持服務,以使每個測試oracle只關注驗證其測試所需的結果,並且設計與時間相關的測試,以允許在非實時操作系統中執行的容差。允許延遲執行5-10%的保證金的常見做法減少了測試執行中潛在的漏報數量。還建議以與生產代碼相同的方式處理測試代碼。測試代碼必須對正面和負面情況正確工作,持續很長時間,並且可讀和可維護。團隊可以聚在一起並審查測試和測試實踐,以分享有效的技術並捕捉壞習慣

3.3 避免的做法,或“反模式”

測試用例取決於從先前執行的測試用例操作的系統狀態(即,您應該始終從已知和預配置狀態開始單元測試)。
測試用例之間的依賴關係。測試用例彼此依賴的測試套件是脆弱且複雜的。不應推定執行令。初始測試案例或UUT結構的基本重構導致相關測試中越來越普遍的影響。
相互依賴的測試。相互依賴的測試可能導致級聯錯誤否定。即使UUT中不存在實際故障,早期測試用例中的故障也會破壞後續測試用例,從而增加缺陷分析和調試工作。
測試精確的執行行爲時間或性能。
建立“無所不知的神諭”。隨着時間的推移,檢查超過必要的oracle會更加昂貴和脆弱。這個非常常見的錯誤是危險的,因爲它會導致複雜項目中的一個微妙但普遍的時間下沉。[11]
測試實施細節。
運行緩慢的測試。

4 TDD軟件

有許多測試框架和工具在TDD中很有用。

4.1 xUnit框架

開發人員可以使用計算機輔助測試框架,通常統稱爲xUnit(源自1998年創建的SUnit),以創建並自動運行測試用例。xUnit框架提供斷言式測試驗證功能和結果報告。這些功能對於自動化至關重要,因爲它們將執行驗證的負擔從獨立的後處理活動轉移到測試執行中包含的活動。這些測試框架提供的執行框架允許自動執行所有系統測試用例或各種子集以及其他功能。[32]

4.2 TAP結果

測試框架可以接受1987年創建的與語言無關的Test Anything Protocol中的單元測試輸出。

翻譯自 : https://en.wikipedia.org/wiki/Test-driven_development

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章