淺論如何做好單元測試提升軟件質量
一、單元測試的意義
單元測試會為我們的質量做保證。編寫單元測試就是用來驗證這段代碼的行為是否與我們期望的一致。有了單元測試,我們可以自信的交付自己的代碼,而沒有任何的后顧之憂。
我們在編碼時,一定會反復調試保證它能夠編譯通過。如果是編譯沒有通過的代碼,沒有任何人會愿意交付給Boss。但代碼通過編譯,只是說明了它的語法正確;我們卻無法保證它的語義也一定正確,沒有任何人可以輕易承諾這段代碼的行為一定是正確的。
從成本角度考慮,BUG發現越早越好,加強單元測試力度有利于降低缺陷定位和修復難度,從而降低缺陷解決成本,同時加強單元測試也減輕了后續集成測試和系統測試的 負擔。據業界統計,如果一個BUG在單元測試階段發現花費是1的話,到集成測試就變為10,到系統測試就高達100,到實際推向市場量產后就高達 1000,所以,進行充分的單元測試,是提高軟件質量,降低開發成本的必由之路。但單元測試在目前國內軟件企業中開展得并不好,一方面是由于對單元測試重 視程度不夠,測試投入不足,另一方面是由于在單元測試實踐方面積累得也不夠,單元測試處于一種摸索狀態。
單元測試不僅僅是作為無錯編碼一種輔助手段,在一次性的開發過程中使用,單元測試必須是可重復的,無論是在軟件修改,或是移植到新的運行環境的過程中。因此,所有的測試都必須在整個軟件系統的生命周期中進行維護。
單元測試與其他測試不同,單元測試可看作是編碼工作的一部分,應該由程序員完成,也就是說,經過了單元測試的代碼才是已完成的代碼,提交產品代碼時也要同時提交單元測試代碼。測試部門可以對單元測試的過程以及結果作一定程度的審核,作為集成和系統測試準入的一種標準。
二、如何做好單元測試
1)組織結構應該保證測試部門參與單元測試
目前普遍都認為單元測試應該由開發人員開展,這是因為從單元測試的過程看,單元測試普遍采用白盒測試的方法,離不開深入被測對象的代碼,同時還需要構造驅動模塊、樁函數,因此開展單元測試需要較好的開發知識。從人員的知識結構、對代碼的熟悉程度考慮,開發人員具有一定的優勢。
單元測試由開發人員進行能帶來一些特別的收益。我們知道,在實踐中開發人員進行單元測試一般推薦采用交叉測試的方法,例如由被測單元的調用方進行該單元 的測試,即盡量避免對自己的代碼進行單元測試。這種交叉的測試安排可以避免測試受開發思路影響太大,局限于原來的思路不容易發現開發過程中制造的問題;二 來也達到一個技術備份或充分交流的目的,這對組織非常有利。即使不采用交叉測試的方法,而安排單元的生產者自行開展單元測試,也是有很大的優越性的,其最 大的優點是快速。在人員緊張的情況下這種自行測試的安排也是不錯的選擇。
從經驗值來看,單元測試投入和編碼投入相比基本上是一比一,如果由專職測試隊伍來進行單元測試,維持這樣龐大的單一任務隊伍顯然是不合適的,對于一般企業來說也是不小的成本負擔。
以上談的是由開發人員進行單元測試的優點,其中主要是從單元測試的效率角度來考慮。但是從單元測試效果的角度考慮,必須從組織結構上保證測試部門參與單元測試,這是因為:
首先,從目前國內企業普遍現狀來看,測試人員質量意識要高于開發人員,測試人員參與單元測試能夠提高測試質量。
其次,對被測系統越了解,測試才有可能越深入,測試人員參與單元測試,將使得測試人員能夠從代碼級熟悉被測系統,這對測試人員后期集成測試和系統測試活動非常有幫助,會很大的提升集成測試和系統測試質量。
測試部門以何種方式參與單元測試,應該結合軟件組織的實際情況來定。如果軟件組織測試充分,測試人員對開發人員的比例較高,那么可以由測試人員獨立承擔 部分重要模塊的單元測試工作;如果測試資源不足,測試人員對開發人員的比例較低,那么可以采取由測試人員進行單元測試計劃、單元測試設計的工作,而單元測 試的實現和執行由開發人員來完成;而如果測試資源非常缺乏或測試人員素質不夠全面,連單元測試計劃、單元測試設計都無法承擔,那么測試部門至少應該參與開 發過程的各相關單元測試文檔、單元測試報告的評審,保證單元測試的質量。軟件質量的提高需要規范的流程,對軟件開發過程進行管理也需要依據規范的過程定義。要提高單元測試的質量,首先要制定規范的單元測試過程,各生產部門可以依據單元測試過程定義開展各自的工作,共同保證單元測試的質量。
單元測試過程的定義需要參照企業的實際情況,例如階段劃分可以分為四個階段:計劃、設計、實現、執行。
其中計劃階段應當考慮整個單元測試過程的時間表,工作量,任務的劃分情況,人員和資源的安排情況,需要的和測試方法,單元測試結束的標準等,同時還應當考慮可能存在的,以及針對這些風險的具體處理辦法,并輸出《單元測試計劃》文檔,作為項目中整個單元測試過程的指導。
設計階段需要具體考慮對哪些單元進行測試,被測單元之間的關系以及同其它模塊單元之間的關系,具體測試的策略采用哪一種、如何進行單元測試用例的設計、如何進行單元測試代碼設計、采用何種工具等,并輸出《單元測試方案》文檔,用來指導具體的單元測試操作。
實現階段需要完成單元測試用例設計、腳本的編寫,測試驅動模塊的編寫,測試樁模塊的編寫工作,輸出《單元測試用例》文檔、相關測試代碼。
執行階段的主要工作是搭建單元測試環境,執行測試腳本,記錄測試結果,如果發現錯誤,開發人員需要負責錯誤的修改,同時進行回歸測試,該階段結束需要提交《單元測試報告》。我們可以將設計和實現階段合并,輸出《單元測試用例》文檔、相關測試代碼。
3)必須制訂覆蓋率指標和質量目標來指導和驗收單元測試
單元測試必須制訂一定的覆蓋率指標和質量目標,來指導單元測試設計和執行,同時作為單元測試驗收的標準。設計用例時,可針對要達到的覆蓋率指標 來設計用例,而在測試執行時,可以依據覆蓋率分析工具分析測試是否達到了覆蓋率指標,如果沒達到,需要分析哪些部分沒有覆蓋到,從而補充用例來達到覆蓋率 指標。而單元測試質量目標的制訂,需要符合軟件企業的實際過程能力,這依賴于軟件企業對以前單元測試過程度量數據的積累,不能憑空制造出來。有了以前度量 數據的積累,完全可以了解當前組織的單元測試能力,例如單元測試每千行代碼發現的缺陷數是多少。如果單元測試統計結果沒有落到這個質量目標范圍內,說明單 元測試過程中某些方面存在一些問題,需要對測試過程進行分析后找出問題原因進行改進。
這些指標確定下來后,一定要嚴格推行。定會有一些人找出各種理由證明覆蓋率指標達不到等等,這需要質量部門根據實際情況分析指標是否合理。實際 證明有一個相對簡單的標準也比沒有標準要好得多,但顯然,通過推行硬性指標,單元測試發現的問題數目比沒有標準前至少增加了2倍。
4)單元測試者技能的提高
1、加強對單元測試人員的技能
單元測試的質量很大程度上決定于進行單元測試的人的技術水平。如果測試者不具備單元測試的知識,那么應該對測試者進行相關的培訓。一個沒有做過 單元測試人,不經過培訓初次是很難做好單元測試的。單元測試在詳細設計階段結束時開始,但是單元測試相關培訓應該盡早準備和計劃,培訓可以分兩個階段,每 個階段的內容類似。第一階段是寫單元測試方案前,培訓對象為測試方案的寫作者和詳細設計的寫作者,這樣可以在設計時多考慮可測試性,培訓的內容為單元測試 基本概念、單元測試分析方法、單元測試用例的寫作、單元測試標準的明確;第二階段為單元測試執行前,對象為測試執行者,培訓內容為具體單元測試的執行,包 括驅動函數、樁函數的構造、覆蓋率測試工具的使用(TrueCoverage、Logiscope等)、利用自動化單元測試框架構造單元測試自動化 (TCL、CppUnit、JUnit等)。培訓過程中最好結合實例穿插其中,會比較生動,而且增強理解。
通過以上的系統培訓,可以統一單元測試方法、明確單元測試的標準、掌握單元測試基本技能,為后期單元測試的順利開展掃平道路。
2、必須引入工具進行輔助
單元測試非常需要工具的幫助,特別是覆蓋率工具不能缺少,否則用例執行后無法得到測試質量如語句覆蓋、路徑覆蓋等情況,也就無法對被測對象進行 進一步的分析。應用較廣的分析覆蓋率的工具有Logiscope、TrueCoverage、PureCoverage等,它們的功能有強有弱,可以根據 實際情況采用。
為了提高單元測試的效率,特別是提高進行回歸測試時的效率,需要在單元測試中引入自動化。目前常用的方法是采用TCL語言編寫擴展指令,構造自己的單元測試自動化。也可以直接采用開源的自動化測試框架如CppUnit、JUnit等。
此外,在單元測試之前,還需要利用PC_Lint對被測代碼進行檢查,排除代碼語法錯誤,確保進行單元測試的代碼已經具備了基本質量,保證單元測試能夠順利進行,提高單元測試執行效率。
3、單元測試者加強對被測軟件的全面了解
單元測試的目的除了要發現編碼中引入的錯誤和發現代碼與詳細設計不一致的地方之外,還有一個目的是為了保證詳細設計的質量。因為測試分析和測試用例設計需要依據詳細設計來進行,這個過程實際上是對詳細設計的重新檢視,在這個過程中會發現以前評審中沒有發現的問題。
我們公司的單元測試才剛剛起步,質量體系中尚無明確的規范,程序員對單元測試的意識也較淡薄。雖然在推行單元測試上取得了一些進步,但很難落實 到實際的環節上,很多都是走過場的。不少程序員覺得任務大,時間趕,人手少,一接到任務就是先趕代碼完成工作量了,這其實是很普遍的現象。而且,絕大部分 程序員從骨子里不喜歡寫單元測試,這卻是不爭的事實。我們公司的開發人員在單元測試上多是走過場,而測試人員也只涉及到存儲過程的單元測試,且沒有單元測 試用例,測試方法存在誤區,導致測試帶有隨意性,效率低下。
要做好單元測試,還必須充分考慮到公司自身的實際情況。基于我們公司目前的諸多現狀,結合項目具體實際情況,在公司某一項目中,對單元測試做了如下理論結合實際的應用。
1、項目經理在項目計劃的過程定義文件中明確單元測試作為本項目的過程,確定在單元測試的各個階段的工作產物;
2、項目經理制定單元測試計劃,明確測試目標、測試方法、準入準則、準處準則、單元測試數據、單元測試工具、人力資源計劃、進度計劃;
3、開發人員在編碼前設計測試用例,并且準備單元測試代碼及設計文檔,項目組組織人員評審,測試人員必須參加;
4、開發人員在編碼完成提交產物前,必須做單元測試,可以是自測,也可以是開發人員互測,發現的缺陷必須提交缺陷庫,并提交單元測試報告。在人力資源緊張時,可以由測試人員執行單元測試;
5、有了單元測試的缺陷數據,我們就可以分析,一般常見的缺陷有哪些類型,如何改進;還可以發現哪些開發人員的編碼質量,為獎懲提供依據。
四、結論和展望
總而言之,單元測試將讓我們的開發工作變得更加輕松,讓我們對自己的代碼更加自信。無論是項目的規模大小,無論是時間緊迫的項目還是時間寬裕的項目,只要代碼不是一次寫完永不改動,編寫單元測試就一定超值。我希望它能成為我們公司編碼過程中不可缺少的一部分。
單元測試僅僅是軟件質量保證的一個環節,軟件的質量由組織、流程和技術三個維度來決定,任何一個維度都不能單獨決定軟件的質量。好的組織結構可 以保證流程的順利實施,好的流程能提高軟件開發的規范性和可控性,從而提高軟件開發的效率和質量,而采用了好的技術和有好的技術的載體--人,則從根本上 保證了軟件的質量。
該項目在落實以上措施后,達到了一下效果:
1、在一定承擔上提升了軟件交付質量;
2、測試部門反映:有效降低集成和系統測試投入的成本;
3、項目執行周期比預期的縮短。
因此,論證了單元測試在軟件生產過程中作用。