什么是單元測試?

  一直以來大家有一種錯誤的理念,總是認為單元測試作為一種測試方法,主要是由測試工程師來主導的一種測試手段。并非如此,借用教科書上的說法,單元測試作為一種最基礎的測試手段,其主要作用是“在計算機編程中,針對程序模塊(最軟件設計中的最小單元)進行正確性檢驗的測試工作。”

  之前曾經閱讀過一篇文章,作者提了一個例子,他說他兒子在使用樂高積木做玩偶過程中,組裝完一些零部件之后,就會試圖去測試一下部件是否能夠正常運轉,作者說這種過程實際上就是一種單元測試。他認為,單元測試的思想其實普遍存在于人類文明的發展過程中,從人類開始制作工具來說,就需要使用單元測試的方法對工具的可用性進行測試。尤其是進入工業時代以來,傳統制造業尤其重視產品質量,為了提高產品質量,采取了一系列措施,這種例子其實不勝枚舉。

  去年我曾經有幸為一家國企開發過一些質量管理系統,并深入了解了這些企業的質量管理流程,雖然從宏觀層面來看,以互聯網經濟為代表的新興經濟對以包括制造業在內的實體經濟帶來了許多沖擊,但是依然那些優秀的制造業企業依然堅定的將產品質量作為核心競爭力,并通過互聯網的這種模式,讓企業的發展獲得了新的機遇。

  軟件行業其實本質上和制造業沒有那么巨大的區別,以軟件開發過程中,由軟件工程師們開發出來的每一個方法實際上就是開發者們解決虛擬世界生存問題的零部件,每一個產品或應用就是這樣的工具。在一個軟件開發過程中,往往需要涉及到多人操作,經常需要調用別人編寫的模塊代碼。尤其是在面向互聯網開發中,如果不能認真的對待每一行代碼,就有可能一些疏忽大意造成不可彌補的后果。

  因此做好單元測試,不僅僅只是開發者們應該采用的一種測試手段,而是應該是一種基本的技術手段,對我們開發的每一行代碼,都應該使用單元測試進行覆蓋,自己負責的模塊定義應該盡量明確,模塊內部的更改不會影響他模塊,讓模塊的質量得到穩定和良好的保證。

  為什么大家認為單元測試不合時宜?

  當然,大部分開發者也許明白這個道理,但是卻認為單元測試不合時宜,主要包括以下幾點:

  1,沒有時間

  ---- 在軟件開發過程中,往往以完成任務為第一要務,而由于時間計劃的安排,單元測試的設計和實踐均需要花費大量的時間完成,過度的使用單元測試會拖延項目的進度,而且花費的邊界成本高昂而收效甚微。

  ---- 筆者認為,跟隨代碼一起,設計和應用單元測試,并不會顯著的帶來時間上的損害,反而會讓開發者更加關注代碼本身的目的,讓輸入輸出和計算過程更為合理。

  2,計劃會變化:需求變化快,單元測試跟不上需求的變化

  由于軟件產品需求的不確定性,導致之前設計的單元測試并非符合項目的實際功能性需求,沒必要花費這個精力設計這種沒用的場景。

  ----筆者認為,需求變化與是否應用單元測試關系不大。

  3,單元測試是用來找Bug的,應該有測試來編寫

  單元測試作為一種測試手段,是為了發現代碼中存在的bug。

  --- 筆者認為:單元測試的目的是為了讓程序作者更加快捷的發現代碼中存在的問題,并在第一時間發現和解決,從而保障軟件質量。

  4,有程序員定義的單元測試沒有意義,因為程序員設定的邏輯場景就有可能不準確

  單元測試作為由程序員根據實際用例出發設計的測試流程,本身可能并非符合業務的實際應用需要,因此單元測試應該由最了解需求的人來進行設計。而且完成單元測試設計后,也需要有了解需求的人對單元測試用例和代碼進行審查。

  --- 筆者認為:由程序員開發的單元測試沒有意義,那么他寫的代碼呢?寫代碼本身就是為了完成指定的用例場景,如果單元測試都不合理,那么如何確保代碼本身就合理?

  5、TDD測試驅動,不過是一種形式主義,本身就不合時宜

  在TDD模式中,測試先于開發,所以需要經過良好的設計和定義,最好能夠解耦合各個模塊,讓代碼更加完美的匹配測試代碼。但是這種代碼本身就要求經驗豐富的開發者才能完成,而能夠完成這種能力的,本身就屬于優秀開發者,并不需要設計單元測試代碼。

  -- 筆者認為:優秀的開發者,本身不僅僅只是因為他們出身優秀,而是因為他們掌握了包括單元測試等在內的優秀學習方法并每天都在實踐。

  好的單元測試的標準

  筆者最近閱讀《構建之美》(第一版)深刻認同提出的關于好的單元測試的標準,例如以下幾點:

  1、單元測試應該在最低的功能參數上驗證程序的正確性。

  2、單元測試應該由最熟悉代碼的人(程序的作者)來寫。

  3、單元測試過后,機器狀態保持不變。---筆者認為,不僅僅機器的狀態應該保持不變,數據中存儲的數據關系也應該保持不變,例如,通過單元測試錄入的數據,應該在完成測試后自動回滾,或者添加測試戳記后,手動清除。

  4、單元測試要快(一個測試的運行時間是幾秒鐘,而不是幾分鐘)。

  5、單元測試應該產生可重復、一致的結果。

  6、單元測試具有獨立性的特點,單元測試的運行、通過、失敗不依賴于別的測試,可以認為構造數據,以保持單元測試的獨立性。

  7、單元測試應該負載所有的代碼路徑。

  8、單元測試應該繼承到自動測試的框架中。

  9、單元測試必須與產品代碼一起保存和維護。

  何妨不試一試呢?

  在軟件企業的發展前期,往往會由于技術上的一些偶發性突破,取得短期的優勢,但是隨著企業的規模發展,使用更加規范化甚至成為形式化的方式確保產品的質量是必然趨勢,而單元測試則是一種看似簡單,但卻效果顯著的手段,相信通過一段時間的實踐,就會深刻的領悟到其中的妙處。