前言
對測試人員或程式開發人員來說,單元測試是一個常被使用也相當重要的工具,撰寫此篇文章的目的,除在於介紹單元測試基本概念外,並將介紹如何在Visual Studio 2008開發環境中產生單元測試,最後提供一些單元測試實務經驗,供讀者參考。
單元測試簡介
一、何謂單元測試
為了確保所撰寫的程式,能夠符合程式開發要求,因此需要一些測試方法,例如壓力測試、整合測試、單元測試等,而單元測試則是其中一種重要的方法,單元測試(Unit Test)又稱之為模塊測試,所謂的單元(Unit),即為最小的單位,常指的是函數或類別的方法。
一般而言,單元測試是由程式開發者本身撰寫的,程式每修改一次程式,就須要做一次單元測試,因此單元測試在整個程式開發下來會被執行相當多次,甚至有可能會要求每天必須被執行一次,以檢查程式所產生的結果,是否符合需求規格。
單元測試最簡單的測試方法,就是輸入預先設計好的資料,經過程式流程之後,看看其輸出的結果,是否能符合程式規格書所要求的內容。
二、單元測試目的
單元測試的目的,在於開發階段即可幫助程式開發人員發現各類別元件可能發生的邏輯錯誤,以確保程式所產生的結果能符合需求。
除此之外經由單元測試的報告,也能夠幫助開發人員減少抓取臭蟲的時間、縮短開發時程,且有助於提升程式品質與穩定性,使開發人員對於程式的品質及可靠度更有把握。
而在每一次程式修改或更改版本時,執行所有的單元測試,則能夠有效避免因為沒有發現邏輯錯誤,而將有邏輯錯誤的程式更新的情況發生。
三、單元測試流程
在一般單元測試當中(如圖一),會在程式碼當中加上Assert 陳述式 (Statement),其能夠用來檢核測試結果是否符合預期,檢核的內容可以有很多種,若沒有加上這段陳述式,則是單純測試這組參數是否能夠成功執行這支程式而不產生錯誤或例外。
《圖一》
為了能夠使單元測試能重覆執行,因此筆者通常會再加上準備測試環境及還原測試前環境等更複雜的流程,而這些流程將在下文介紹。
產生單元測試在Visual Studio 2008之下,我們能利用自動產生測試的方式產生所需測試,但若是在較複雜或無法接觸到原始碼的情況下,就必須使用手動方式來產生單元測試。
一、自動產生單元測試其實在Visual Studio 2008開發環境當中,已有相當方便的工具,我們可以利用自動產生測試的方法來產生所需測試,其操作方式如下:
1. 在要測試的程式碼上,按右鍵,點選「建立單元測試」
《圖二》建立單元測試
2. 勾選要建立的測試的方法,按下確定。
《圖三》選取要建立的單元測試
3. 開啟產生的測式程式
《圖四》開啟測試程式
4. 自動產生單元測試的成果
《圖五》產生的結果
二、手動產生單元測試手動產生單元測試,運用在較複雜或無法看到程式原始碼的情形下,作法即是以手動方式加入一個新的測試。
1. 在要測試的方案上,按右鍵,選擇加入裡面的新增專案。
《圖六》加入專案
2. 在「加入新的專案」視窗中,選擇測試中的測試專案,再按確定。
《圖七》選擇加入測試專案
3. 在測試專案當中,按右鍵,選擇加入中的新增測試
《圖八》選擇新增測試
4. 「加入新測試」,依照要測試的內容選擇,本例是選「單元測試」
《圖九》加入單元測試
5. 開始撰寫單元測試
《圖十》開始撰寫單元測試
撰寫單元測試實務與技巧一、單元測試目標與原則在說明單元測試技巧之前,先說明單元測試的一些基本目標與原則,這些原則能夠幫助我們撰寫單元測試的時候較有方向。
◎互相獨立
首先每單元測試間,必須互相獨立,例如:有兩個單元測試,程式A是執行讀取出某個資料表,而程式B測試刪除某個資料表,那先執行B之後再執行A就有可能造成讀不到資料而失敗的情形。
又或者測試程式A,但是在測試程式A之前又依靠新增某個資料表的程式C,這種情況有可能因為程式C的Bug而誤以為程式有錯誤。
因此在執行每一個測試之前,都應該先獨立準備每一個測試的環境,也避免使用其它元件來準備測試的資料,而產生相互干擾的情形發生。
◎可重覆被執行
單元測試,有可能是每次過版或每天都固定時間要被執行一次,因此如何使得單元測試能被不斷的重覆執行,是相當重要的。
◎程式涵蓋率
單元測試的目的,就是在發現程式當中,可能沒有被發現到的臭蟲(bug),因此將每段程式碼執行一次,便是較能夠確保每種可能性都被執行到的指標,如何提高單元測試的程式碼執行涵蓋率,且盡量達到100%,是單元測試的重要指標。
二、單元測試技巧為了達到上述單元測試的目標,因此筆者提供一些撰寫單元測試的心得與技巧。
◎標準化單元測試格式
首先,先分享筆者撰寫單元測試時,有標準化程式的固定格式,一般而言,筆者在測試程式撰寫時,會將單元測試分為下列四個部分,分別為「準備測試環境」、「執行測試」、「檢核測試結果」、「還原測試前的環境」。
1.準備測試環境
準備測試環境,就是準備要輸入程式的資料及程式執行時會用到的環境;環境的準備是以最簡單的方式下SQL指令新增資料到資料庫當中。
例如:下圖十一測試程式讀取書本資料,那麼在測試之前就以下SQL指令的方式先新增要被讀取的書本資料進去,那麼就能夠確保接下來讀取書本資料時會有資料可以讀取。
《圖十一》讀取書籍資料流程
2.執行測試
在準備動作完成後,則將資料輸入到受測程式中,經過程式流程之後,並接收其測試的結果。
3.檢核測試結果
判斷檢核測試的結果是否符合預期,檢核的方式有很多種,根據不同測試個案有不同檢核方式。
例如:預期回覆成功而成功,預期回覆失敗而失敗,或預期為新增某筆資料到資料庫當中。
4.還原測試前的環境
也就是資料還原的動作,即是將為了測試而產生的資料以及測試後產生的資料從資料庫或檔案中刪除,還原到測試以前的環境,如此一來下次再執行單元測試的時候就可以避免因為資料而產生的錯誤。
筆者將單元測試分成這四部分的目的,即是能夠確保單元測試撰寫原則當中的「重覆執行」及「互相獨立」的原則,同時由於程式的標準化,讓將來單元測試維護時更為容易。
◎了解程式流程與架構
程式的測試,以程式透明性來說,可分為兩種,一種是黑箱測試,另外一種為白箱測試;黑箱測試指的是我們無法看到程式裡面的運作流程,這種測試就只能依靠程式規格書等資料來設計測試個案。
而白箱測試就是能看到程式流程的測試,在白箱測試中若我們能了解要被測試的程式的流程與架構,那麼就能夠設計出接近程式涵蓋率100%的單元測試個案,以符合「程式涵蓋率」的原則。
《圖十二》書籍歸類程式流程
例如:圖十二為簡單的書本分類程式,當我們了解到程式有三個可能性之後,那麼就能輕易的設計出「雜誌」、「漫畫」及「一般書」的三種案例。
◎撰寫測試所用到的公用子程式
這部分主要是針對標準化測試格式,當中的「準備測試環境」及「還原測試環境」來多做說明,比較算是程式撰寫的一些心得與技巧。
《表一》測試成功案例
《表二》測試失敗案例
上面兩張表格,分別是測試「新增」、「刪除」、「修改」、「查詢」資料表的四隻程式的成功與失敗案例。
在測試「新增」資料表的程式中,成功就是沒有相同的資料存在,新增一筆會成功;而新增失敗的方法,就是先新增一筆相同的資料,在測試的時候就會因為已經有重PK重覆而失敗。
同樣的情形在刪除、修改與查詢當中,我們會發現到,它都會一直使用到「新增測試資料」、「刪除測試資料」這兩組動作,因此,我們可以將這兩個動作,獨立出來成為測試時所用到的公用子程式(Sub),這樣一來不僅可以節省撰寫單元程式的時間,同時由於新增及刪除的資料統一,也方便測試資料的統一管理。
◎使用大綱
最後則是介紹如何使用大綱Region,這部份也比較算是程式撰寫的技巧,同樣以表1與表2為例,在測試「新增」、「刪除」、「修改」、「查詢」四個程式的成功與失敗,就有8個單元測試程式了。
若在這時候,要做這四組動作的資料表又有8個,那麼就至少會有64個單元測試,程式碼編輯器當中,就會非常的複雜且多,因此如何讓程式撰寫時,方便日後的管理,我們可以使用Region這標記;圖十三示範Region的使用方式,而圖十四為使用後的成果。
《圖十三》大綱使用方式
《圖十四》摺疊大綱
結論單元測試對於程式開發者及測試人員,是相當重要的工具,其不僅能驗證程式結果是否符合SPEC,也能透過這種方式找出程式的Bug,幫助開發者對於所開發的程式更有信心,減少開發及測試的時間;而透過本篇文章,希望能提供讀者了解單元測試,並且學習到一些單元測試的技巧。
參考資料JUnit Gossip: 單元測試Huan-Lin 學習筆記 on DotBlogsMSDN單元測試概論- Areca ChenStdExt - C++ STL Extensions-好的單元測試標準The Will Will Web