當前位置:
首頁 > 科技 > 當我們在談論單測時我們在談論什麼

當我們在談論單測時我們在談論什麼


關於如何提升團隊的代碼質量,我曾經做過很多嘗試。由於團隊成員都有繁忙的開發工作,公司也不是學校,不可能投入太多去面面俱到地教層層選拔招聘進來的程序員這些基礎知識,所以,做法一般是以點帶面,比如引入 sonar 代碼檢查推動大家去掌握一些以前未曾注意到的編碼細節,比如通過針對性地培訓降低代碼的認知複雜度讓大家掌握常用的重構技巧和設計方法。這些都能取得一定的效果,這次我想從自動化單元測試入手,更進一步……

什麼是單元測試

教我的兒子 Allen 學習 Scratch/Python 和樂高是我周末最主要的一項「娛樂活動」,從孩子的視角去看待和學習編程語言和工程技術會給人很多意想不到的啟發。正如上面的圖片所示,有一次,Allen 在用樂高積木做一輛小車,當他把輪子組裝好的時候,他會用手指撥弄一下,看輪子能不能轉動。這時車子還遠遠沒有成形……他竟然在做單元測試!!!

Allen 的這一個舉動讓我感到驚喜,我甚至開始幻想他未來一定會成為一個出色的工程師!他明白儘可能早,儘可能小地去做單測,這已經超過我工作中見過的 80% 的軟體工程師了,在我看來,我所見過的大部分開發者做單測的時機都不夠早,單元的粒度也不夠小。

後來我看了一部名為《狼伴歸途》的電影,這部電影讓我意識到我陷入了「自己家的孩子,別人家的老婆,怎麼看都覺得好」的思維誤區里——Allen 明白的「儘可能早,儘可能小地做單測」的這個道理,我們的祖先在石器時代就已經明白了。

他們在製作長矛的時候,先會用石頭打磨矛頭,每磨一段時間,他們就會將即將成形的矛頭在皮毛上劃一下,驗證矛頭是否足夠鋒利,只有矛頭合格了,才會給它裝上一個長柄。

想想我們工作中整日忙碌,把自己還不太清楚是否足夠鋒利到能刺破動物皮毛的矛頭和滿是低級缺陷的粗糙的長柄迅速組裝起來匆匆提測並交付給獵人的程序員們,被大家戲稱為程序「猿」其實是實至名歸——大部分人的技藝還處在非常原始的狀態,還沒有進入石器時代。

「儘可能早,儘可能小地做單測」 是我們這支人類賴以繁衍下來的最基本技能,它已經固化到 Allen 的基因里形成了固有行為模式。


為什麼要做單元測試

孩子和原始人進行單元測試是基於一種本能或傳統,他們不知道這背後的深層次原理。當我們提到測試的時候,不得不提到的是這個測試金字塔。

測試金字塔有多種的分層方式,上面這幅圖引自《The Clean Coder》,不論哪種分層方式,其背後體現的經濟學原理是一致的。

首先,越是在底層的測試類型,其測試的成本越低,反饋越及時。在單元測試階段能發現的一個缺陷,假設修復它的成本是 10 塊錢,那如果它沒有在這個階段被發現,而是推遲到了組件測試階段,那修復它的成本是 100 元,以此類推,每晚一個階段發現,其修復成本都會增加一個數量級——想一想那高昂的溝通和回歸成本吧。如果在線上才發現這些缺陷,那成本和損失就更難以估量。

基於上面的原理,專業的開發團隊應該選擇一個合理的測試策略。

首先是測試覆蓋率的要求不一樣。單元測試的覆蓋率終極目標可以追求 100%,但系統測試能做到 10% 就已經很昂貴了。

其次,是每種測試類型的關注內容應該不一樣。單元測試關心代碼層面的正確性,大多數的異常路徑都是由單元測試來覆蓋的,單元測試應該由開發者自己來做,組件測試更多關心成功路徑的情況,以及一些明顯的極端情況、邊界狀態和可選路徑,組件測試可以由 QA 和業務人員來負責。

軟體在其生命周期內會頻繁地變更,這和建築物、飛機汽車等非常不同,充分體現了軟體」軟「的一面。在這種高度變化的環境下,要每次做到這麼高的測試覆蓋率,成本是巨大的。幸好,也正是由於軟體」軟「的一面,自動化的測試在軟體領域更容易實現。


什麼是自動化單元測試

自動化單元測試 = 自動化 單元 測試

最近,我調研了一些自動化單元測試覆蓋率是個位數的應用,下面用實例來說明什麼不是自動化單元測試,然後大概就清楚了為什麼對很多開發者來說自動化單元測試那麼難。

我還遇到一些高級的開發者,他們不會犯上面這些低級的錯誤,他們甚至在自動化測試方面做了很多有價值的創新。比如,他們把線上的真實入參數據抓下來,變成 XML/JSON 數據,然後基於這些數據寫單元測試。這種做法的一個主要問題是站的角度不對,這種測試是黑盒的,記得我們上一節說過吧,單元測試要覆蓋大部分異常情況,抓再多的真實數據,也很難保證覆蓋到大部分的異常,因為很多異常狀況的發生概率本來就低。單元測試要覆蓋大部分異常情況就必須有一部分是站在白盒的角度來寫的。另外這種測試方式維護成本也很高,你仔細考量,它其實是測試金字塔里的組件測試。這種測試是有價值的,但更適合 QA 團隊來負責。

以上種種都說明很多情況都做不到自動化,這是阻礙自動化單元測試落地的一個重要原因,但其實還有更深層的原因存在。

如何做好自動化單元測試

這個更深層次的原因就是單元,既然單元測試位於組件測試之下,那單元的粒度比組件還要更小。要做好單元測試,首要條件是要有單元。如果組件內的代碼沒有分成清晰獨立的小單元,那單元測試就無從談起。所以,三分測試,七分設計。

如果能將代碼合理地拆分成不同的單元,你就會發現,大部分單元,如圖中綠色部分所示,都是非常獨立的,它們不依賴資料庫等外部資源,只是一個內存的計算,所以這部分是非常容易做自動化單元測試的。

不好做單元測試往往是膠水單元和有外部依賴的單元。而這部分代碼往往不是業務邏輯所在,代碼結構也比較扁平,並不複雜。

所以,當你的應用的自動化單測覆蓋率只是個位數時,先不要急著引入 MOCK 框架這類工具,當務之急是做這種單元化的改造,測試那些投入產出效果明顯的部分。以後再用 MOCK 等方式測試其他部分。

誠然,做好單元測試有很多方法、技巧和工具,但首先我們會聚焦在這一點上。


最重要的事

你無法做好你不理解、不認可的事情。

這是我接觸到的優秀的敏捷教練用行動告訴我的。在做敏捷實施的時候,首先要做的是培訓敏捷的理念(你可以稱之為"洗腦"),培訓結束後,你的團隊如果無法理解和接受敏捷的核心理念,優秀的敏捷教練一般都會告訴你,敏捷其實也要因地制宜,其實你們現在團隊的做法就挺好的。

是的,如果你不認可這一篇文章所說的大部分理念,我想說的是,不做自動化單元測試也沒什麼,非常多成功的市值上千億的互聯網公司開發的軟體都有著非常低的單測覆蓋率。生命苦短,不要在單測這種小事兒上浪費時間。

作者:codeasy,志在分享哪些讓編碼變得簡單的軟體技藝——包括原則、技術、工具和實踐。

聲明:本文為作者投稿,版權歸對方所有。

熱 文推 薦


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 CSDN 的精彩文章:

Dubbo 沉睡,Spring Cloud 崛起!
VS Code 正在統治代碼編輯器領地!

TAG:CSDN |