單元測試實施解惑——無縫整合

在剛過去的一個月中,我完成了一個小軟件框架的設計與實現。期間由於並行開發的需要,在沒有對代碼完成單元測試的情形下我將之check in到了SVN的主幹上,隨後的心情很是忐忑。因爲我知道我一定會犯錯(事實也證明在單元測試完成之前就發現了兩個缺陷),害怕給他人帶來麻煩並影響自己的形象。

另外,由於對剛加入項目的單元測試環境完全不瞭解,所以在該框架的前期開發工作中我並沒有運用單元測試漸進地保證軟件質量。其結果可想而知,我花了不少時間去修復編碼過程中遺留下來的低級錯誤。需要指出的是,所在項目是一個大型嵌入式系統,項目編譯一次就得20分鐘左右,調試效率可以想象。與之不同的是,單元測試可以在Linux/Cygwin這樣的環境中完成,加上可以使用gdb進行調試,開發效率提高一個數量級應不是問題。

由於我深刻地體會到了單元測試對工作與生活質量的重要性,所以持“真正高質高效的軟件開發工程師,一定是那些深刻理解並切實實施單元測試的人”這一觀點。然而,就我過去幾年的工作見聞來看,發現身邊絕大多數的工程師並沒有真正用心去擁抱單元測試。出現這樣的狀況,我認爲存在一定的原由,因此想借本文談談一些認識。

有相當一部分工程師是因爲並不瞭解什麼是單元測試而沒能嚐到單元測試的好處。一部分人認爲,平時開發工作中的調試其實就是單元測試(參見《明析單元測試》),有的則因爲沒有花時間學習單元測試而對之不瞭解。對於這些新手,我並不打算在本文對之“掃盲”,請下載ClearRTOS源碼點擊下載和本文的附件自行學習。 ClearRTOS 是我爲《專業嵌入式軟件開發》一書所設計的、可在Cygwin和Linux環境中運行的“實時”操作系統,其中涵蓋有單元測試方面的內容,更具體的信息見文後。

另外的一部分人儘管實施過單元測試,但卻沒能從中受益,甚至得出“單元測試無用”的結論。這部分人的困惑是我最想在這裏加以指出的。歸結起來,我認爲實施過程中的“縫太大”是其中一大主因。

不少團隊將項目的產品代碼與單元測試代碼加以區別對待,這是產生“縫”的第一大根源。表現之一是,編譯產品代碼與編譯單元測試代碼採用完全不同的編譯環境,程序員在日常工作中需要不停地在兩個編譯環境中進行切換。這種方式很容易讓工程師感到麻煩,甚至因此遭到抵制或棄用。好的方式是,將單元測試代碼的編譯環境與產品代碼進行無縫整合。比如,在嵌入式系統項目中做到運行“make release”或“make debug”實現產品代碼編譯,運行“make unitest”完成單元測試代碼編譯(ClearRTOS項目就是這麼做的)。做到編譯環境的無縫整合需要團隊中存在精通編譯環境構建語言(比如Makefile)的專家。很不幸的是,這方面的專家少得可憐,團隊對這方面知識的精進也因爲沒有意識到其重要性而缺乏動力。

表現之二是,產品代碼與單元測試代碼區別維護。採用這種方式的團隊,很容易在工作中將單元測試擺到更低的位置,開發過程會先以產品代碼爲主,然後(有時間時)再補上單元測試代碼。這種方式很容易降低實施單元測試的效果,且容易因爲產品代碼與單元測試代碼的不同步而帶來更大的維護成本。實際上,實施單元測試的一大好處就是在對產品代碼進行變更時,通過及時實施單元測試保證軟件質量。及時維護單元測試代碼從短期和長期都具有很好的經濟性,而非象我們想象的那樣成本高昂。

產生“縫”的第二大根源,是因爲工程師在單元測試過程中不能方便地獲得代碼覆蓋報告。以我的觀點,代碼覆蓋報告應在開發環境中運行象“make creport”這樣的命令而輕鬆獲得(ClearRTOS項目同樣實現了這一點)。我看到過一些項目,工程師爲了獲得覆蓋報告,需要登錄到一個Web服務器上才能查看,而非在工程師的工作機器上隨手獲取。

產生“縫”的另一大根源與單元測試的“打樁”方法有關。被廣爲採用的方法是通過使用象Cmockery這樣的單元測試框架以打樁的形式,將被測模塊獨立出來。這種方式儘管被廣泛採用,但我覺得所需付出的成本還是很高的。因爲“樁的世界”與“產品代碼世界”存在很大的“縫隙”,維護期間需要不停地在兩個“世界”進行切換,更好的方式是將樁代碼融入到產品代碼中(細節我想通過另一篇文章給出)。

儘管我認爲單元測試是一種有效的質量保障方法,但其有效性在工程界和學術界都存在一定的爭議。也正因此,我正以《軟件企業成功實施單元測試的關鍵因素研究》爲題,作爲我MBA的畢業論文。懇請您花上5分鐘左右參與研究問卷調查(點擊這裏參與),後面我會通過博客公佈研究結果。
 
關於ClearRTOS
ClearRTOS現在是一個開源項目(鏈接),讀者可以通過SVN獲取將來的新版本。爲了能在ClearRTOS項目中獲得HTML格式的代碼覆蓋報告,讀者需在Linux/Cygwin中安裝LCOV(鏈接)。
 
在ClearRTOS項目中獲取代碼覆蓋報告的步驟如下:
    1)運行“tar xzvf ClearRTOS.tar.gz”解壓。
    2)運行“cd ClearRTOS/build”進入編譯目錄。
    3)運行“make unitest”編譯單元測試程序。
    4)運行“make test”執行單元測試程序。
    5)運行“make creport”獲取單元測試報告。報告可用IE、Chrome等瀏覽器打開ClearRTOS/build/coverage/index.html文件進行瀏覽。通過點擊網頁中的相關鏈接可以查看到每個源文件的代碼覆蓋情況。

《專業嵌入式軟件開發》相關節選
 
26.3.2 構建有效方法論的核心手段
有了工具和流程並不表示質量保證方法論就一定有效,還需要注意它們的可操作性和易用性。有效的質量保證方法論源於構建手段。
 
26.3.2.1 關鍵要素有形化
在保證軟件質量的關鍵要素中,大體上可以將其分爲有形的和無形的兩大類。是否有形是指能否通過一定的具體方法施加影響以保證軟件質量。比如,設計能力和編程好習慣一開始就不是一種有形的要素,而工具、文檔卻是有形的。
 
將無形要素有形化是打造質量保證方法論的核心手段之一。對於好的設計思想這一無形的要素,可以通過抽取設計原則,以文檔化的方式使其有形;對於編程好習慣也可以通過文檔將其有形化;等等。有形化的要素容易在項目團隊中被學習和實踐,使這些要素在人的行爲中體現“形”。
 
一個好的質量保證體系應儘可能地將無形的要素轉換成有形的,以便減少其中難以控制的“藝術”成份而獲得良好的可操作性。
 
26.3.2.2 流程和工具的無縫整合
對於質量保證方法論中的工具和流程,應儘可能地將它們與項目開發環境進行無縫整合,無縫整合的目的在於保證易用性。工具和流程只有易於使用,才能在項目團隊中最大限度地發揮其價值。另外,將一些重複性的工作自動化,也是提高易用性的一種方式。
 
軟件開發是一種將無形的需求有形化的過程,有形化後的產物從項目團隊的角度來說就是代碼。由於代碼是無形需求的外在表現,因此代碼的質量對於整個軟件產品的質量具有決定性的意義。先不說代碼在設計上做得如何,但無論怎樣的設計所獲得的代碼都不應當包含編碼錯誤。因此,爲了保證代碼的質量,需要通過運用工具和方法來找出其中存在的錯誤。圖26.2示例說明了應與開發環境無縫整合的工具和方法。
 
無縫整合的結果是工程師能輕鬆地使用它們,並體會到其所帶來的益處。不少工具和方法之所以不能被持久地運用而發揮作用大多是因爲使用起來太麻煩,乃至工程師還沒有嚐到 “甜頭”就放棄了。軟件產品的質量源於對每一個軟件模塊的質量把控,因此開發環境中無縫整合的工具和方法應被應用於每一個軟件模塊的編碼過程,也只有這樣質量管理才能落到實處。
 
26.3.2.3 以單元測試爲中心
爲了獲得更好的易用性和效果,在構建質量保證方法論時應做到以單元測試爲中心。請不要將“單元測試爲中心”理解爲“只要做好單元測試就能保證軟件質量”。圖26.3示例說明了哪些方法和工具應以單元測試爲中心。

前面提到,軟件產品質量的保證在很大程度上需要通過代碼質量保證加以落實,而單元測試能做到最小粒度的代碼功能驗證。單元測試需要通過設計測試用例保證代碼儘可能多地被執行,這也正是代碼覆蓋、動態分析和性能分析所需要的。將代碼覆蓋、動態分析和性能分析以單元測試爲中心進行整合,能實現通過進行單元測試“順便”完成以之爲中心的其他質量保證工作。
 
以單元測試爲中心這一手段有點抽象,在第29、31和32章讀者將看到是如何通過以單元測試爲中心方便地完成代碼覆蓋、動態分析和性能分析的。

本文出自李雲的博客,請務必保留此出處:http://blog.csdn.net/hzliyun/article/details/7935695。
 
發佈了63 篇原創文章 · 獲贊 331 · 訪問量 40萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章