如題,我是一位初學者,現有一道題如下:
編一段代碼,分別實現插入排序,合並排序和快速排序的算法。然後編寫測試代碼,設計測試數據集,編寫測試程序,測試正確性、算法復雜性和效率。
題目中注明檢測正確性的測試程序應該輸出一個遍歷結果,保證所有分支語句都檢測到。不太理解這是要我做什麼……以及比較算法復雜性、效率,是需我明確地輸出花費時間嗎?
希望有大神可以在測試代碼這方面指點迷津,謝謝!
"主要是你要准備足夠充分的測試數據,這樣才能保證代碼的覆蓋率。"
這種說法是不對的。測試就是要用盡可能少的測試用例,對代碼做盡可能全面的測試。構造測試用例是一個需要技巧的工作。“充分、足夠的數據”是一個模糊的概念,如果不加選擇的使用大量測試數據,不但大大增加測試花費的時間,而且對於一些代碼路徑,仍然可能無法覆蓋。
這裡舉一個例子:
int foo(int x, int y, int z)
{
if (z == 0)
{
x = 1;
y = -1;
}
if (x > 0)
{
if (y > 0)
{
return 1;
}
else
{
return 2;
}
}
else
{
if (y > 0)
{
return 3;
}
else
{
return 4;
}
}
}
對於這樣一段代碼,要想在測試中覆蓋所有的代碼路徑,需要設計至少多少個測試用例?
答案是8種:
x y z
-1 -1 0
-1 1 0
1 -1 0
1 1 0
-1 -1 1
-1 1 1
1 -1 1
1 1 1
可見,覆蓋所有代碼路徑就是,確保程序的所有分支的排列組合都嘗試過。
現在再問你,要覆蓋所有的代碼分支,又需要多少測試用例?答案是5種
x y z
1 1 0
-1 -1 1
-1 1 1
1 -1 1
1 1 1
(當然答案不唯一)
可見,覆蓋代碼分支,就是確保代碼中所有的分支都執行到。但是不覆蓋全部的排列組合。
在真實情況下,覆蓋所有路徑往往是辦不到的,因為程序大一些,那麼分支組合的數量是天文數字。一般我們考察的是代碼分支的覆蓋率。在完備的測試中,要求100%覆蓋所有的代碼。
是不是覆蓋了所有的路徑(如果可能)就能確保程序正確?不一定,因為即便是同一個路徑,也可能因為不同的測試數據,而造成不同的行為。
所以,構造測試用例是一個非常有技巧的事情。測試者必須根據他的經驗,盡可能測試到極端的、臨界的條件,將從概率上很低發生但是可能導致程序出錯的條件提取出來。