I. 前言
測試驅動開發是一個現在軟件界最流行的詞匯之一,可是很多人還是不得其門而入。這篇文章想通過對于CppUnit的介紹,給予讀者一個基本的映像。如果你熟知CppUnit的使用,請參閱我的另一篇文章:CppUnit代碼簡介 - 第一部分,核心類來獲得對于CppUnit進一步的了解。
II. 測試驅動開發
要理解測試驅動開發,必須先理解測試。測試就是通過對源代碼的運行或者別的方式的檢測來確定源代碼之中是否含有已知或者未知的錯誤。所謂測試驅動開發,就是在開發前根據對將要開發的程序的要求,先寫好所有測試代碼,并且在開發過程中不時地通過運行測試代碼來獲得所開發的代碼與所要求的結果之間的差距。很多人可能會有疑問:既然我還沒有開始寫代碼,我怎么能夠寫測試代碼呢?這是因為,雖然我們還沒有寫出任何實現代碼,但是我們可以根據我們對代碼的要求從使用者的角度寫出測試代碼。事實上,在開發前寫出測試代碼,可以檢測你的要求是不是完善和精確,因為如果你寫不出測試代碼,表示你的需求還不夠清晰。
這篇文章通過一個文件狀態操作類來展示測試驅動開發相對于普通開發方法的優勢。
III. 文件狀態操作類(FileStatus)需求
構造函數,接受一個const std::string&作為文件名參數。
DWORD getFileSize()函數,獲取這個文件的長度。
bool fileExists()函數,獲取這個文件是否存在。
void setFileModifyDate(FILETIME ft)函數,設定這個文件的修改日期。
FILETIME getFileModifyDate()函數,返回這個文件的修改日期。
std::string getFileName()函數,返回這個文件的名字。
IV. CppUnit簡介
我們所進行的測試,某種意義上說,就是一個或者多個函數。通過對這些函數的運行,我們可以檢測我們是否有錯誤。假設我們要對構造函數和getFileName函數進行測試,這里面有一個很顯然的不變式,就是對一個FileStatus::getFileName函數的調用,應該與傳給這個FileStatus對象的構造函數的參數相同。于是我們有這樣一個函數:
bool testCtorAndGetFileName()
{
const string fileName( "a.dat" );
FileStatus status( fileName );
return ( status.getFileName() == fileName );
}
我們只需要測試這個函數的返回值就可以知道是否正確了。在CppUnit中,我們可以從TestCase派生出一個類,并且重載它的runTest函數。
class MyTestCase:public CPPUNIT_NS::TestCase
{
public:
virtual void runTest()
{
const std::string fileName( "a.dat" );
FileStatus status( fileName );
CPPUNIT_ASSERT_EQUAL( status.getFileName(), fileName );
}
};
CPPUNIT_ASSERT_EQUAL是一個宏,在它的兩個參數不相等的時候,會拋出異常。所以,理論上說,我們可以通過:
MyTestCase m;
m.runTest();
原文轉自:http://www.anti-gravitydesign.com