标簽: 單元測試 前言 系列
- 單元測試之道
- 1. 前言
- 2. 單元測試總覽
- 2.1 什麼是單元測試(WHAT)
- 2.2 為什麼使用單元測試(WHY)
- 2.2.1 快速定位
- 2.2.2 文檔記錄
- 2.2.3 适應變更
- 2.2.4 規範設計
- 2.3 什麼時候決定進行單元測試(WHEN)
- 2.4 怎麼進行有效的單元測試(HOW)
- 參考資料
-
前言
===
在一個項目當中,開發者常常要做大量的測試工作,如單元測試,內建測試,回歸測試,壓力測試 .etc。當然,依據項目情況大小和開發者人員水準不同,測試涵蓋的方面自然也是不一樣的。一些測試需要相應的硬體和人力資源,一些需要專門的測試小組,另一些需要提供細緻處理和長時間不間斷運作的環境。
但是今天說的單元測試則不同,它是一種看起來十分廉價和基礎的技術。它由背景程式開發人員建立運作,單機運作,刨除代碼量以外,對一個完整的項目開發成本而言,所需的人力物力都是相對較小的。而長久以來的事實也已經證明,單元測試對于代碼規範性和高效性,以及項目Bug的捕獲和解決都有很大的幫助。大多數開發者其實了解這樣的事實,隻是因為一些内在和外在的因素(通常是不重視,時間緊和嫌麻煩),往往不願意進行這些測試,或者隻在項目快要結束時才想起來,隻是已經為時已晚。
是以諸如TDD(測試驅動開發)的項目開發方式,都提倡一個核心道理:單元測試應該早做,多做,這樣既避免了過度設計,對有效編碼,項目依賴解耦也有好處。而且我們始終要明确,單元測試的第一受益者,永遠是程式員。接下來,就讓我們來看看單元測試的一些相關情況,之後再在.NET項目中實際運作單元測試吧。
- 單元測試總覽
讓我們根據3W+1H原則,先對單元測試有個系統性認識吧
當我們在談論單元測試的時候,我們在談些什麼。——村上春樹
按照維基百科上的說法,單元測試(Unit Testing)又稱為子產品測試, 是針對程式子產品(軟體設計的最小機關)來進行正确性檢驗的測試工作。程式單元是應用的最小可測試部件。在面向對象程式設計中,最小單元就是方法,包括基類、抽象類、或者派生類(子類)中的方法。按照通俗的了解,一個單元測試判斷某個特定場條件下某個特定方法的行為,如斐波那契數列算法,冒泡排序算法。
單元測試将被測試應用程式細分為一個個足夠小的基本單元,各個單元間互相獨立,互不影響。開發者能通過單元測試,證明被測試函數的行為确實和開發者期望的一緻。為了滿足這個最基本的願望,書寫單元測試前,我們不用考慮太多關于性能上的事情,這是之後優化重構該做的事情。
愛做單元測試的程式員,代碼都不會太差。——古龍
上文說到,常常由于項目工期緊張,抑或是程式員自身原因的問題,團隊往往在項目接近完成時才進行測試。這其實是非常不提倡的一種做法。就好像我們雇了一批人給我們造房子,從地基開始,造到十幾層了,才用懸垂線來測房子傾斜度一樣不靠譜(假如這個比喻靠譜的話)。到時候高層依賴底層,高層調試時發現bug,又得讓我們傳回底層查找問題,即便修改之後仍然通過了,但是想必很多朋友也遇到過項目代碼覆寫度比較高,一改基礎方法影響一大片的問題吧。
是以當我們從一開始就進行正确的單元測試時,這些問題都是可以解決的。以下羅列出了幾個簡單的作用,以供參考
單元測試最基本的一個功能,就是快速定位代碼中的錯誤。從項目一開始,開發者便對所有的單元子產品進行測試的話,,除了能盡早發現問題,另一方面對我們項目的持續開發無疑也是提供了極大的保障。
當我們設計出一個良好的單元測試環境,我們勢必會對所有的基本單元進行測試,這時候,單元測試相對于為我們編寫了一份api文檔,我們随時可以查閱方法相關參數和傳回值,以及運作情況。
單元測試允許程式員在之後的開發工作中重構代碼,并且確定單元依然工作正确。這個過程就是為所有函數和方法編寫單元測試。在連續的單元測試環境中,隻要設計出了良好的驗證手段,單元測試可以延續用于準确反映當任何變更發生時可執行程式和代碼的表現,幫助開發者優化代碼邏輯和代碼結構。
進行單元測試時,開發者其實站在了一個觀察調試的上帝角度。無論是開發先于測試,還是測試先于開發,單元測試都可以幫助我們将子產品設計成易測試,易調試,易重構。在這個過程中,開發者的編碼能力和對業務的了解能力也将得到鍛煉
早。——魯迅
單元測試這東西,就跟戒煙一樣。每個煙民都知道吸煙的壞處(bug),一開始吸煙的時候也會有人提醒你趕快戒煙吧,但是你往往并不在意,等到年限一長(項目開發疊代多次),因為吸煙身體出現的問題越來越嚴重,你可能在這之前做過幾次體檢(內建測試),但是依然于事無補了,等這時候再懷念當初戒煙,乃至不抽煙的好,也是為時已晚。是以單元測試,就該在項目一開始的時候進行測試,在你起了“編寫單元測試太麻煩了,還是算了”的念頭的時候就該開始。部落客代碼水準有限,無止盡的debug和bug送出已經耗費了我很大的精力,是以這才下定決心開始單元測試之旅。
确實不可否認,剛開始就編寫單元測試常常要多花費幾倍的代碼量,但是随着項目進行,當你把基礎方法都測試過以後,高層功能需要的代碼量反而會大大減少。這時候單元測試也在往內建測試遷移,這是一個順其自然的過程,同時為內建測試的簡化也提供了極大的便利。
單元測試最終呈現出來的效果還是一個或多個測試方法而已,編寫這些測試方法時,應該注意以下原則
- Arrange 用于初始化一些被測試方法需要的參數或依賴的對象。
- Act方法 用于調用被測方法進行測試。
- Assert 用于驗證測試方法是否按期望執行或者結果是否符合期望值
在這之前,我們當然需要區分出應用程式的每個基本單元,這裡有個讨巧的方法,就是對項目依賴進行自底而上的周遊即可,我們并不需要多在意單元測試和內建測試的依賴關系。
其實在傳統的DDD驅動開發中,我們已經見識了很多IAPPService和IRepository,以及IDomainService的依賴關系了,對于多個基本單元測試組裝的內建測試,我們這裡也統一當做同一種東西來對待了,畢竟我們關注的還是測試本身。所謂工欲善其事必先利其器,.NET 平台上強大的工具也是必不可少的,下文中将用XUnit和NSubstitute來進行所有的測試用例展示。
——未完待續
- 單元測試-維基百科
- 單元測試(C#版)
- Test Driven Development
- 前後端分離開發模式下後端品質的保證 —— 單元測試