綠燈 | 紅燈

妙思資訊

2011年11月27日 星期日

你開發的程式好測試嗎(一)?

有寫過單元測試(Unit Test)的開發人員因該都有這種感覺,"測試碼比程式碼還要難寫"。要讓所設計的程式可自動被測試,這可是一門學問;更進階的測試手法還可搭配Mock或Reflection來達成。今天先談基本的單元測試,進階的測試未來再詳述。

1. 單元測試是各自獨立的
單元測試是沒有依賴性或先後順序的。如果測試程式彼此間有互相依賴,就不易進行自動化測試,因為在執行自動化測試時,通常是隨機進行,而不會按照一定的順序去執行測試。當然,有的測試會按測試名稱的英文字母順序來執行,但是當接手的人把測試名稱改了,之前所調好的順序又會大亂;再來測試有依賴性,容易因某人改了程式,而造成其它的測試程式測試失敗。

2.單元測試的範圍是有限制的 例如:只測DAO這層或只測Service這層,如果Service有呼叫DAO這層,那在測Service這層時,也會再測一次DAO,這樣就跨了二層,而不是一個單元了。如果DAO已經測試過,每次測Service層時,是否還要再把DAO拉進來一起測呢?如果拉進來測,那又會跟Database綁在一起,測起來就很沒效率。
如果要讓Service層做到所謂的單元測試,可以使用Mock來模擬DAO的行為,將DAO  Mock  Inject 到Service 中,這樣就可把DAO切開,單純地測試Service 的邏輯。因為測試Service層時,不會再和Database 連結,所以測試的速度可以快上一倍。以前曾參與開發一個大型系統,這個系統有近2千支的測試程式,全部跑完CI測試需45分鐘,之後我們將Service中的DAO改為Mock,則CI只要花20分鐘就跑完所有測試。所以Database是關鍵,使用Mock 將Database 和Service分離,大大的提升CI的效率。
測試包含了黑箱測試、白箱測試、Web 測試、整合測試、Javascript 測試、Stored Procedure 測試、壓力測試、安全性測試和使用者測試...等。除了使用者測試外,其它都可撰寫測試碼進行自動化測試,只要程式能夠被自動化測試,程式的品質和設計就比較不會有問題。
要寫好單元測試是要一點時間,當你發現程式很難測的時候,就代表你可能要變更設計了。程式不易被單元測試的常見的情況有:

1. 程式無聲無息的做完了,沒有提供任何訊息可供判斷!

2. 傳入到Method的參數,型態為底層的Interface!因為跟底層綁在一起,不好測!

3. 在Method中有new 底層的物件或服務。這些物件可能必須配合系統的環境才可生成,在測試環境也許生不出這些物件。

4. Method中有使用Singleton物件。 (Singleton Is Evil,少用)!

5. Method中有使用非同步運算,測試都是針對Current Thread,非同步的Thread要由另一個測試程式來測。如果非同步是和Mail Server 有關,只能測到信有送出,至於是否有收到信,就不是單元測試的範圍了。

6. 你想測的是 Private Method.  若是.NET 開發人員,Visual Studio 可自動利用Reflection 的機制來對Private Method 進行測試,JAVA的開發人員,就沒有這麼好的工具。當然,還是有方法可以測,只是比較麻煩!


待續...

沒有留言: