程式碼只有CRUD,好像沒單元測試好寫?
沒想到這題會變成有網友敲碗要求解答的問題?
我在TW MVC的 .net conf mini 研討會中,大致描述了在 DevOps 採行高強度的持續交付時,團隊應該要做單元測試(unit test, UT)的原因。
議程後,有學員提問:『老師建議要做unit test,但同仁的程式碼大多是CRUD,似乎沒什麼測試好寫的? 這樣要如何提高測試程式碼覆蓋率?』
當時我的答案是:『如果真沒什麼東西好測的,那就別寫了,不需要為提高覆蓋率來硬寫測試程式。』這個答案乍聽之下可能讓人疑惑,特別是那種對於工程技巧實踐極端渴望,到近乎有些強迫症的工程師。
然而,現場學員這個問題的背後,真正的核心問題應該是,為何你寫的程式碼都沒啥東西可測的?
要探索這個問題,得先回到單元測試的本質。我們之所以要寫單元測試,大約有底下幾個原因:
- 減少人工手動測試,建立自動化回歸測試。 or
- 將測試案例(test case)自動化。
- 確認重要的核心邏輯程式碼不會出問題(確認你的程式碼堅固且可被驗證)
- 提高可維護性的確據(確保不會改了這邊,壞了那邊)
- 便於類別開發(例如開發API、或商業邏輯類別函式庫)
- …
差不多上面這些,是我聽到大多數人想做單元測試的原因。
但問題來了,我在養成班或是許多剛進入開發領域的工程師身上,大多碰到一個問題。就是…他手上寫的程式碼幾乎都是很基本的資料庫CRUD,再不然就是畫面UI的處理,就還真沒什麼複雜的邏輯,程式碼主要的工作差不多都是 ==> 取得畫面上用戶輸入的欄位,然後呼叫EF(entity framework)做資料庫的寫入,或是反過來,從資料庫把資料讀出來,然後呈現在畫面上。
『這樣的程式碼,要怎麼寫單元測試?』學員問。
的確,這樣的程式碼,確實沒什麼重要的單元測試好寫。因為,你既不需要去測試EF(entity framework, ORM),也不應該去測試UI是否正確的把你需要的畫面呈現出來,因為這都是框架本身已經做好的事情,若你的程式碼中沒有什麼運算邏輯,卻花大把時間去寫測試,似乎有點划不來。你真正要測試的對象,應該是你自己撰寫的『邏輯』。
一般我在上課的時候,大多用撰寫BMI計算、或是轉換匯率的類別來當作Unit Test範例,是因為它們都有明確的處理邏輯,如果程式碼大多只是為了做輸出輸入,撰寫單元測試的意義就不大。
我跟學員說 : 『你還記得小時候的電腦教學101?』
輸入 --> 處理 --> 輸出
還記得嗎?
我們所撰寫的『程式碼』的核心功能,應該有一些『處理(process)』的部分,撰寫單元測試理當以這些部分作為首要重點。而這些負責處理(process)的程式碼,我們大多會寫成類別(Class)。所以,如果你有撰寫類別,並且為類別撰寫很多方法(method),那你應該就會有很多單元測試需要寫。
同學說: 『我沒有。我大多數程式碼都只有呼叫別人寫好的類別,很少(幾乎沒有)自己寫什麼類別庫。』
我說:『那這樣,即便你硬去做單元測試,十之八九你實際上做的是「整合測試」,而非「單元測試」。』
單元測試的主要目的,是撰寫程式碼來測試特定的功能(function)或方法(method)函式,以確保該函式的運作邏輯是正確的。而我們大多在MVC框架中,寫在controller裡面的程式碼,都只是呼叫(調用)其他的類別(例如資料庫處理、Log處理、UI處理),倘若有複雜的邏輯運算程式碼(例如算薪資、剩餘休假時數、費用帳單…etc.),你就應該將其從controller中抽出,把它寫成類別,然後在controller中去呼叫(這個你撰寫的類別),如此一來,你寫了類別,自然就需要為此類別撰寫單元測試了。
如果開發人員總是把這些運算邏輯,一股腦寫在controller中,或是寫在UI的 event handler 中,那你當然覺得沒啥測試好寫,而且,這樣也大大失去了你使用MVC框架開發的意義了。
『所以,或許我們可以這樣說』我跟學員說道:『只要你撰寫類別,幾乎跑不掉一定會需要撰寫測試程式。而如果你在撰寫程式時,幾乎不用寫什麼類別,那你的程式一定有些什麼問題。要麼是相依性、耦合性太高,要麼是本身的商業邏輯太少,而這多半也意味著這種程式碼的value偏低。』
『那如果我負責撰寫的程式碼真的就只有一堆的表單,只需要依照資料庫的結構,把相同的欄位設計成畫面UI,並且進行CRUD(新增、讀取、更新、刪除),只是數量非常非常多(大概上百上千隻),那我該做什麼?』另一位同學問。
『那你該做的是換工作。』我說:『因為,這類的工作其實用程式碼產生器(code generator)大多就可以處理,而不需要花費人力。不然,你就乾脆嘗試寫一個表單程式碼產生器,可以偵測資料表結構,一口氣把成千上百隻表單自動產生出來。這樣,你的貢獻程度將遠遠超過人工去做那一兩百隻表單。』
『而且,開發表單產生器(form generator)的過程中,你將會有數不盡的單元測試必須做。』我笑著回答。
留言