產品函數:
void CMyClass::Grow(int years)
{
mAge += years;
if(mAge < 10)
mPhase = "兒童";
else if(mAge <20)
mPhase = "少年";
else if(mAge <45)
mPhase = "青年";
else if(mAge <60)
mPhase = "老年";
mAge = 8;
pObj->Grow(years);
ASSERT( pObj->mAge == 9 );
ASSERT( pObj->mPhase == "兒童" );
}CaseEnd();
在輸入數據中對被測試類的成員變量mAge進行賦值,在預期輸出中斷言成員變量的值,F在可以看到我們所推薦的格式的好處了吧,這種格式可以適應很復雜的測試。在輸入數據部分還可以調用其他成員函數,例如:執行被測試函數前可能需要讀取文件中的數據保存到成員變量,或需要連接數據庫,我們把這些操作稱為初始化操作。例如,上例中 ASSERT( ...)之前可以加pObj->OpenFile();。為了訪問私有成員,可以將測試類定義為產品類的友元類。例如,定義一個宏:
#define UNIT_TEST(cls) friend class cls##Tester;
然后在產品類聲明中加一行代碼:UNIT_TEST(ClassName)。
下面談談測試用例設計。前面已經說了,測試用例的核心是輸入數據。預期輸出是依據輸入數據和程序功能來確定的,也就是說,對于某一程序,輸入數據確定了,預期輸出也就可以確定了,至于生成/銷毀被測試對象和運行測試的語句,是所有測試用例都大同小異的,因此,我們討論測試用例時,只討論輸入數據。
前面說過,輸入數據包括四類:參數、成員變量、全局變量、IO媒體,這四類數據中,只要所測試的程序需要執行讀操作的,就要設定其初始值,其中,前兩類比較常用,后兩類較少用。顯然,把輸入數據的所有可能取值都進行測試,是不可能也是無意義的,我們應該用一定的規則選擇有代表性的數據作為輸入數據,主要有三種:正常輸入,邊界輸入,非法輸入,每種輸入還可以分類,也就是平常說的等價類法,每類取一個數據作為輸入數據,如果測試通過,可以肯定同類的其他輸入也是可以通過的。下面舉例說明:
正常輸入:
例如字符串的Trim函數,功能是將字符串前后的空格去除,那么正常的輸入可以有四類:前面有空格;后面有空格;前后均有空格;前后均無空格。
邊界輸入:
上例中空字符串可以看作是邊界輸入。
再如一個表示年齡的參數,它的有效范圍是0-100,那么邊界輸入有兩個:0和100。
非法輸入:
非法輸入是正常取值范圍以外的數據,或使代碼不能完成正常功能的輸入,如上例中表示年齡的參數,小于0或大于100都是非法輸入,再如一個進行文件操作的函數,非法輸入有這么幾類:文件不存在;目錄不存在;文件正在被其他程序打開;權限錯誤。
如果函數使用了外部數據,則正常輸入是肯定會有的,而邊界輸入和非法輸入不是所有函數都有。一般情況下,即使沒有設計文檔,考慮以上三種輸入也可以找出函數的基本功能點。實際上,單元測試與代碼編寫是“一體兩面”的關系,編碼時對上述三種輸入都是必須考慮的,否則代碼的健壯性就會成問題。
文章來源于領測軟件測試網 http://www.kjueaiud.com/