代碼測試的簡單框架
發表于:2007-11-22來源:作者:點擊數:
標簽:單元測試
寫完代碼后,你當然要測試它。有許多種方法來測試代碼:你可以在你的代碼中加些斷點,或者觀察實際發生的情況并和你預計的結果相比較,又或者寫些測試程序等等。 給代碼寫測試通常是測試代碼的最好方法。因為寫出來的測試可以一遍又一遍地執行。當你修改了實
寫完代碼后,你當然要測試它。有許多種方法來測試代碼:你可以在你的代碼中加些斷點,或者觀察實際發生的情況并和你預計的結果相比較,又或者寫些測試程序等等。
給代碼寫測試通常是測試代碼的最好方法。因為寫出來的測試可以一遍又一遍地執行。當你修改了實現,你可以再次運行測試來檢查一下你是否引入了任何
bug。這種方法可以將你從調試中拯救出來,并引領你生產出具有更低錯誤傾向的代碼。
作為一個一般的方針,在
開發你的測試的時候,我們建議你不要把結果打印到屏幕上;而是,根據輸入數據,用asserts創建一個后置條件指明期望得到哪些輸出數據。
如果你在運行測試時把結果打印到了屏幕上,開始時你會去分析這些結果。然而,隨著時間延長,你會越來越不注意這些打印到屏幕上的數據。即使數據指出了一個錯誤,你也可能不會意識到。
此外,如果別的人試著運行測試,他們不得不首先弄明白這些打印出來的數據是什么意思,這可能要花不少時間。反過來,如果你用了asserts,人們就只要去運行你的測試。如果發生了錯誤,他們會被提示在哪一行發生了錯誤,他們就可以去修正它。
這兒是一個測試例程的例子:
#include
#include
// 整理一個字符串的前導和追尾空白,
// 返回整理后的字符串
std::string trim_spaces( const std::string & str)
{
/* trim_spaces 的實現*/
}
void testTrimSpaces()
{
assert( trim_spaces( " abc") == "abc");
assert( trim_spaces( "def ") == "def");
assert( trim_spaces( " this is a test ") == "this is a test");
assert( trim_spaces( "") == "");
assert( trim_spaces( " ") == "");
}
怎樣建立一個
測試框架,和建立它每一個步驟:
第一步:將測試代碼和實際代碼清楚地分隔開。要做到這一步,一個很簡單的方法是把所有用來做測試的文件都放到一個特別的目錄中去。每個用來做測試的文件的名字都應該以test開頭,然后加上它所測試的模塊/類名。例如,從testWordTokenizer.cpp文件的名字就可以看出,它是用來測試一個斷詞類(word tokenizer class)的。
測試用的代碼僅在執行測試時才被編譯。當生成實際的應用程序時,測試代碼會在預處理階段就被移除。如果我們的每個測試文件都遵循下面的模式就可以保證這一點:
// Test.cpp
#ifdef TESTING
/* testing code*/
#endif // TESTING
// End of file
于是,如果定義了TESTING,我們就是在做測試;否則,我們就是在從實際的代碼生成應用程序。
第二步:所有用來測試代碼片斷的函數的名字都應該以Test或test開頭。對于你所測試的每個模塊/類,都要有一個主測試函數負責調用其他測試函數來測試模塊/類的各個代碼段。這樣你就不需要暴露出所有函數——只要暴露出主測試函數就可以了,像下面的例子:
// TestUrlUtility –用于測試 "Url Utility 函數族"
#if defined( TESTING)
#include "UrlUtility.h"
// 這個命名空間中的函數,從這個源文件外部是不可見的
namespace // 匿名命名空間
{
void TestDivideURL()
{ /* 測試代碼 */ }
void TestIsUrlValid()
{ /* 測試代碼*/ }
void TestIsHttpUrlValid()
{ /* 測試代碼*/ }
void TestParseHttpUrl()
{ /* 測試代碼*/ }
}; //匿名命名空間
// ... 這是從這個源文件外部唯一可見的函數
//
// 我們希望暴露出這個函數;
// 在任意文件中,你可以聲明它的原型如下:
// void TestUrlUtility();
//
// 然后就可以在你的代碼中調用
void TestUrlUtility()
{
TestDivideURL();
TestIsUrlValid();
TestIsHttpUrlValid();
TestParseHttpUrl();
}
#endif // #if defined( TESTING)
// 文件結束
第三步:創建一個測試主文件(大概應該叫做testMain.cpp),其中包含有開始執行測試的main函數。這個“main”函數要做的就是調用各種不同的測試函數。你可以取消希望執行的測試前面的注釋符號,或者把你不想執行的測試注釋掉。它的代碼看起來會是這個樣子:
// TestMain.cpp –用于測試整個應用程序
#ifdef TESTING
#include
// 測試函數開始
// ... 注意:這一部分包含的應該是
// 各個主測試函數(測試整個
// 模塊或整個類的函數)
void TestUrlUtility();
void TestProxyManager();
void TestHttpRequest();
void TestHttpHeaderFields();
// 測試函數結束
/*
用于測試應用程序的各個部分
*/
int main()
{
std::cout << "Testing Application." << std::endl;
// 在這里加入你要執行的測試
// TestProxyManager();
// TestHttpRequest();
// TestUrlUtility();
TestHttpHeaderFields();
// 取消你要執行的測試前面的注釋符號
return 0;
}
#endif
// 文件結束
第四步:有些代碼片斷不應該在測試時被編譯(如用戶界面代碼,真正的“main”函數等)。這些代碼將像下面這樣括起來:
#ifndef TESTING
/* 實際代碼 */
#endif // ndef( TESTING)
第五步:為測試創建一個配置。大多數最新的集成開發環境(IDE)都允許從不同的配置中選擇,并至少提供了兩個缺省配置:debug和release?;赿ebug配置創建一個新的。然后,直接打開TESTING標志。如果用的是g
clearcase/" target="_blank" >cc,那么給編譯參數加上一個-DTESTING標志。如果用的是VC6,在Project Settings | C++ tab | General | Preprocessor處加一個TESTING的定義
原文轉自:http://www.kjueaiud.com