張曉雯++楊健++祁薇
摘要:本文從分析單元測(cè)試中人工測(cè)試和自動(dòng)測(cè)試的特點(diǎn)入手,分析了自動(dòng)測(cè)試的優(yōu)點(diǎn),并選取了流行的開(kāi)源軟件CppUnit作為測(cè)試工具,介紹了使用方法,以及如何建立測(cè)試項(xiàng)目,最終給出基于CppUnit的單元測(cè)試規(guī)范。
關(guān)鍵詞:?jiǎn)卧獪y(cè)試;CppUnit;測(cè)試規(guī)范
中圖分類號(hào):TP311.52 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):1007-9416(2017)02-0079-02
1 單元測(cè)試
在軟件項(xiàng)目研發(fā)過(guò)程中,編碼和單元測(cè)試屬于同一階段,是同樣重要的組成部分。有效適度的單元測(cè)試可以用來(lái)理解和驗(yàn)證代碼的功能特性,是保證軟件質(zhì)量的關(guān)鍵步驟。由于對(duì)單元測(cè)試的覆蓋率要求很高,通常需要反復(fù)的進(jìn)行,因此需要大量的測(cè)試用例,造成人力物力的負(fù)擔(dān)。 還有人認(rèn)為單元測(cè)試就是編寫測(cè)試代碼對(duì)模塊中的類或函數(shù)進(jìn)行測(cè)試,需要很強(qiáng)的編程能力,從而對(duì)單元測(cè)試產(chǎn)生畏難情緒。但實(shí)際上,正確熟練的使用單元測(cè)試工具,開(kāi)發(fā)人員之外的測(cè)試人員也可以很好的完成單元測(cè)試工作。
1.1 單元測(cè)試的分類
按照進(jìn)行測(cè)試的方式分類,基本分為靜態(tài)分析(static analysis)和動(dòng)態(tài)分析(dynamic analysis)。靜態(tài)分析就是對(duì)源代碼進(jìn)行走讀檢查,查找錯(cuò)誤或收集一些相關(guān)數(shù)據(jù),但不用對(duì)代碼進(jìn)行編譯和執(zhí)行。動(dòng)態(tài)分析是觀察軟件執(zhí)行時(shí)的過(guò)程,來(lái)提供跟蹤,及時(shí)間分析,還包含測(cè)試覆蓋度方面的信息[1]。
任何軟件都可以進(jìn)行人工測(cè)試,但進(jìn)行人工測(cè)試可能存在一些問(wèn)題,如:回歸性、效率、覆蓋率、數(shù)據(jù)的重用性問(wèn)題等。測(cè)試工具的出現(xiàn)是為了提高測(cè)試的效率和質(zhì)量,好的工具是測(cè)試工作的有力幫手。
使用測(cè)試工具的自動(dòng)化測(cè)試可以是動(dòng)態(tài)執(zhí)行,也可以是靜態(tài)檢查的方式。自動(dòng)化的靜態(tài)檢查主要根據(jù)代碼的語(yǔ)法來(lái)識(shí)別錯(cuò)誤,測(cè)試工具把這些錯(cuò)誤特征歸納成為規(guī)則庫(kù),掃描代碼時(shí)自動(dòng)與規(guī)則庫(kù)進(jìn)行匹配比較。自動(dòng)化的動(dòng)態(tài)單元測(cè)試通過(guò)執(zhí)行實(shí)現(xiàn)了測(cè)試用例的代碼來(lái)進(jìn)行測(cè)試,測(cè)試工具可以動(dòng)態(tài)生成測(cè)試用例,然后轉(zhuǎn)換到測(cè)試代碼并執(zhí)行。
1.2 選擇合適的單元測(cè)試工具
自動(dòng)化測(cè)試工具的優(yōu)點(diǎn):(1)節(jié)省時(shí)間,免去了重復(fù)的操作;(2)測(cè)試數(shù)據(jù)的可重用性;(3)測(cè)試的可控性。
如果選擇利用測(cè)試工具來(lái)進(jìn)行單元測(cè)試,就要了解如何選擇,如何保證所選工具是最合適的。選擇前要了解測(cè)試環(huán)境、待測(cè)系統(tǒng)類型、開(kāi)發(fā)語(yǔ)言等。
現(xiàn)在市面上常見(jiàn)的C++類的測(cè)試軟件,主要有CppUnit、parasoft公司的C++test、Google公司的GoogleTest以及國(guó)產(chǎn)凱樂(lè)公司的VisualUnit。主要分為開(kāi)源的和非開(kāi)源兩類。開(kāi)源測(cè)試工具具有以下優(yōu)勢(shì):相對(duì)成本比較低;選擇的空間比較大;源代碼開(kāi)放,可以根據(jù)實(shí)際進(jìn)行修改、補(bǔ)充和完善。本文選取開(kāi)源軟件CppUnit進(jìn)行單元測(cè)試工具。
2 單元測(cè)試工具CppUnit特點(diǎn)及安裝
CppUnit是Micheal Feathers由JUnit移植過(guò)來(lái)的一個(gè)在GNU LGPL條約下的并在sourcefogre網(wǎng)站上開(kāi)源的C++單元測(cè)試框架。
2.1 CppUnit的特點(diǎn)
CppUnit是在JUnit成功后,在C語(yǔ)言環(huán)境下開(kāi)發(fā)的白盒測(cè)試工具軟件。CppUnit以靜態(tài)庫(kù)的形式提供給用戶使用,用戶編寫程序的時(shí)候直接鏈接此靜態(tài)庫(kù)就可以了。它提供了一個(gè)簡(jiǎn)單的單元測(cè)試框架,并且為常用的數(shù)據(jù)類型提供了豐富的斷言語(yǔ)句支持。 CppUnit項(xiàng)目被定義為一個(gè)testing framework,其功能很強(qiáng)大,能針對(duì)一個(gè)項(xiàng)目,靈活的提供測(cè)試方案,同時(shí)具備對(duì)測(cè)試用例的管理功能。
2.2 CppUnit的安裝
在官網(wǎng)下載解壓后,子目錄src下已經(jīng)配置好VC的工程文件,其中example文件夾是CppUnit自帶的測(cè)試?yán)?,是針?duì)CppUnit自身的單元測(cè)試集,可以通過(guò)這些例子來(lái)學(xué)習(xí)如何在工程中添加測(cè)試用例。
CppUnit將要進(jìn)行單元測(cè)試管理為樹(shù)狀結(jié)構(gòu)。最小的單元為TestMethod,多個(gè)相關(guān)的TestMethod組成一個(gè)TestCase,多個(gè)TestCase又組成TestSuite。測(cè)試包之間是互相嵌套的,最終形成樹(shù)狀結(jié)構(gòu),用戶可根據(jù)需要選擇任意的樹(shù)節(jié)點(diǎn)來(lái)開(kāi)始單元測(cè)試。
在使用CppUnit前,需要設(shè)置一下相關(guān)的開(kāi)發(fā)環(huán)境。CppUnit提供了兩套實(shí)施的框架庫(kù),一個(gè)為靜態(tài)的lib,一個(gè)為動(dòng)態(tài)的dll。在目錄下,進(jìn)入src文件夾,打開(kāi)CppUnitLibraries.dsw。對(duì)這兩個(gè)project分別進(jìn)行編譯后輸出,輸出的位置為lib文件夾。
最后還要給TestRunner.dll設(shè)置環(huán)境變量。另外一個(gè)要注意的project是TestRunner,它的輸出是一個(gè)dll,它提供了一個(gè)測(cè)試環(huán)境,這個(gè)環(huán)境是基于GUI 方式的,這個(gè)project也需要編譯,輸出位置同樣為lib文件夾。測(cè)試程序要想正確的調(diào)用,它必須位于你的測(cè)試程序的路徑下。
安裝及配置好環(huán)境后,就可以利用CppUnit建立測(cè)試項(xiàng)目了。
3 建立單元測(cè)試項(xiàng)目
在工作項(xiàng)目(Demo)中實(shí)現(xiàn)被測(cè)試的工作類,Sample
Sample.h--
class Sample
{ public:
Sample();
virtual ~Sample();
int Add(int i, int j) {
return i+j; } };
Sample.cpp—
#include "stdafx.h"
#include "Sample.h"
Sample::Sample()
{ }
Sample::~Sample()
{ }
為測(cè)試項(xiàng)目Project(本例為DemoTest)添加測(cè)試類,因?yàn)楸粶y(cè)試的目標(biāo)類為Sample,根據(jù)以上的命名規(guī)則,定義一個(gè)SampleTest的測(cè)試類。
在cpp中將Sample.cpp 包含進(jìn)來(lái),這樣在編譯SampleTest單元時(shí),setUp 中new Sample() 才能找到Sample構(gòu)造函數(shù)的實(shí)現(xiàn)(在Sample.cpp中)。
在測(cè)試項(xiàng)目Project中,新建一個(gè)源文件,這個(gè)源文件要寫測(cè)試項(xiàng)目的main函數(shù),測(cè)試框架如下
#include "stdafx.h"
#include "SampleTst.h"
#include
#include
//以上為相關(guān)的頭文件
int main(int argc, char* argv[])
{
CppUnit::TextUi::TestRunner runner;
CppUnit::TestFactoryRegistry ?istry = CppUnit::TestFactoryRegistry::getRegistry();
runner.addTest(registry.makeTest());
runner.run();
return 0;
}
運(yùn)行Project后,可以看到測(cè)試的結(jié)果。在測(cè)試運(yùn)行過(guò)程中,如果某一assert失敗,測(cè)試函數(shù)執(zhí)行將中斷,而后面的斷言也不會(huì)被執(zhí)行。因此,在設(shè)計(jì)測(cè)試函數(shù)時(shí)應(yīng)盡可能壓縮,使得測(cè)試功能相對(duì)單一。
4 基于CppUnit的單元測(cè)試標(biāo)準(zhǔn)
在相關(guān)測(cè)試項(xiàng)目完成后,測(cè)試人員應(yīng)該刪除無(wú)關(guān)的臨時(shí)文件,保留要提交的項(xiàng)目,并整體保留TestDemo 的目錄結(jié)構(gòu)并進(jìn)行提交。并且要完成相關(guān)的單元測(cè)試總結(jié)報(bào)告[2]。
4.1 測(cè)試結(jié)束后需要提交的測(cè)試產(chǎn)品
(1)每個(gè)被測(cè)類的相關(guān)測(cè)試文檔。
包括測(cè)試類.h頭文件和測(cè)試類實(shí)現(xiàn)的.cpp 文件。
(2)每個(gè)測(cè)試單元的測(cè)試文檔產(chǎn)品。
包含測(cè)試類主函數(shù).cpp 文件。
(3)單元測(cè)試總結(jié)報(bào)告.report。
報(bào)告需要手工填寫,內(nèi)容單元測(cè)試情況的總結(jié)。應(yīng)包括:
被測(cè)類名:項(xiàng)目中所有被測(cè)類的類名;
測(cè)試用例:列出被測(cè)類對(duì)應(yīng)測(cè)試用例及其描述和注釋信息;
正確性測(cè)試報(bào)告:列出測(cè)試單元運(yùn)行的測(cè)試結(jié)果。
4.2 單元測(cè)試工作產(chǎn)品驗(yàn)收規(guī)范
單元測(cè)試通過(guò)的準(zhǔn)則如下:
(1)正確性測(cè)試結(jié)果文件:測(cè)試用例應(yīng)該覆蓋模塊中的所有功能點(diǎn)。
(2)其它測(cè)試特性結(jié)果文件:測(cè)試該模塊要求的其它特性并通過(guò)。
(3)每個(gè)單元的Bug 清單都已更改,不能改正的已給出詳細(xì)說(shuō)明。
(4)單元測(cè)試工作的驗(yàn)收應(yīng)采用同級(jí)評(píng)審的方法,最終由評(píng)審組決定測(cè)試是否通過(guò),從而保證單元測(cè)試的質(zhì)量。
參考文獻(xiàn)
[1]陳能技.軟件測(cè)試技術(shù)大全[J].人民郵電出版社,2015.
[2]李龍等.軟件測(cè)試實(shí)用技術(shù)與常用模板[J].機(jī)械工業(yè)出版社,2013.