歡迎光臨
每天分享高質量文章

為什麼從前那些.NET開發者都不寫單元測試呢?

楔子

四年前我雖然也寫了很多年代碼,由於公司雖然規模不小,卻並非一家規範化的軟體公司,因此在專案中嚴格意義上來說並沒有架構設計、也不寫單元測試,後來有幸加入了一家公司,這家公司雖然也是一家小公司,但是好歹曾經聘請過一位架構師,這位架構師使用spring.net 搭建了一套基礎的技術架構,併在公司推廣使用EnterpriseArchiture(EA)軟體設計UML圖,但是由於種種原因,他試用期還沒過,只是簡單的設計了幾個業務之後就離職了。

我加入這家公司的時候距離這位架構師離職也已經有相當長的時間,未能直接學習的機會,但是非常還能接觸到這位優秀架構師留下來的部分代碼和資料,這為我的職場之路打開了新的窗戶,從這些資料中學到了許多之前一直想學但是沒機會學的內容,並第一次接觸到單元測試這種技術。

然而,值得諷刺的是,在他搭建的專案架構中,單元測試代碼也只有一個簡單的示例,並沒有針對業務功能編寫任何的具體測試代碼,而實際上經手這個專案的開發者已經超過了幾十個人,其實這也從一個側面說明中國相當一部分.Net 開發者跟我一樣,幾乎都不寫單元測試。甚至是不少開原始碼貢獻者,他們貢獻的開源組件,也並沒有設計單元測試的代碼。但是再來看國外的一些優秀的開源組件,往往也都會提供單元測試的代碼,TDD實際上正是一種非常便捷高效門檻低的設計樣式。

後來,我經手的每一個專案都會按照TDD的方式寫單元測試,但是依然沒有深刻領悟單元測試的精髓,只是把它當做代碼除錯的一個入口而已。其實這種單元測試依然不合格,尤其是認真的運行一下代碼改寫率報告之後,就會發現,單元測試的代碼改寫率只有10個點,與微軟的官方標準單元測試改寫率100%相比,簡直就是不合格。

什麼是單元測試?

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

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

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

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

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

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

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

1,沒有時間
—- 在軟體開發過程中,往往以完成任務為第一要務,而由於時間計劃的安排,單元測試的設計和實踐均需要花費大量的時間完成,過度的使用單元測試會拖延專案的進度,而且花費的邊界成本高昂而收效甚微。
—- 筆者認為,跟隨代碼一起,設計和應用單元測試,並不會顯著的帶來時間上的損害,反而會讓開發者更加關註代碼本身的目的,讓輸入輸出和計算過程更為合理。

2,計劃會變化:需求變化快,單元測試跟不上需求的變化
由於軟體產品需求的不確定性,導致之前設計的單元測試並非符合專案的實際功能性需求,沒必要花費這個精力設計這種沒用的場景。
—-筆者認為,需求變化與是否應用單元測試關係不大。

3,單元測試是用來找Bug的,應該有測試來編寫
單元測試作為一種測試手段,是為了發現代碼中存在的bug。
— 筆者認為:單元測試的目的是為了讓程式作者更加快捷的發現代碼中存在的問題,併在第一時間發現和解決,從而保障軟體質量。

4,有程式員定義的單元測試沒有意義,因為程式員設定的邏輯場景就有可能不准確
單元測試作為由程式員根據實際用例出發設計的測試流程,本身可能並非符合業務的實際應用需要,因此單元測試應該由最瞭解需求的人來進行設計。而且完成單元測試設計後,也需要有瞭解需求的人對單元測試用例和代碼進行審查。
— 筆者認為:由程式員開發的單元測試沒有意義,那麼他寫的代碼呢?寫代碼本身就是為了完成指定的用例場景,如果單元測試都不合理,那麼如何確保代碼本身就合理?

5、TDD測試驅動,不過是一種形式主義,本身就不合時宜
在TDD樣式中,測試先於開發,所以需要經過良好的設計和定義,最好能夠解耦合各個模塊,讓代碼更加完美的匹配測試代碼。但是這種代碼本身就要求經驗豐富的開發者才能完成,而能夠完成這種能力的,本身就屬於優秀開發者,並不需要設計單元測試代碼。
— 筆者認為:優秀的開發者,本身不僅僅只是因為他們出身優秀,而是因為他們掌握了包括單元測試等在內的優秀學習方法並每天都在實踐。

好的單元測試的標準

筆者最近閱讀《構建之美》(第一版)深刻認同提出的關於好的單元測試的標準,例如以下幾點:
1、單元測試應該在最低的功能\引數上驗證程式的正確性。
2、單元測試應該由最熟悉代碼的人(程式的作者)來寫。
3、單元測試過後,機器狀態保持不變。—筆者認為,不僅僅機器的狀態應該保持不變,資料中儲存的資料關係也應該保持不變,例如,通過單元測試錄入的資料,應該在完成測試後自動回滾,或者添加測試戳記後,手動清除。
4、單元測試要快(一個測試的運行時間是幾秒鐘,而不是幾分鐘)。
5、單元測試應該產生可重覆、一致的結果。
6、單元測試具有獨立性的特點,單元測試的運行、通過、失敗不依賴於別的測試,可以認為構造資料,以保持單元測試的獨立性。
7、單元測試應該負載所有的代碼路徑。
8、單元測試應該繼承到自動測試的框架中。
9、單元測試必須與產品代碼一起儲存和維護。

何妨不試一試呢?

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

由於時間倉促,可能沒什麼乾貨,下一篇再進一步討論單元測試、代碼改寫率的問題。

原文地址:https://www.cnblogs.com/xiyuanMore/p/10618130.html

赞(0)

分享創造快樂