學(xué)以致用,單元測(cè)試的工具越來越多,可是想找一篇如何單元測(cè)試的文章卻很難。所以偶來寫一點(diǎn)自己的心得,也是一步步摸索著。
先從測(cè)試一個(gè)方法開始,偶隨便找了一個(gè)小算法。這個(gè)方法看來正合適:不能太簡(jiǎn)單,比如一加一等于二;也不能太復(fù)雜,比如牽涉到數(shù)據(jù)庫(kù)操作。
這個(gè)算法的功能是取得小于Max的N個(gè)隨機(jī)不重復(fù)正整數(shù),代碼如下:
public static List<Int32> GetRandomNum(int Max, int N)
{
List<int> Source = new List<int>();
List<int> Result = new List<int>();
for (int i = 0; i < Max; i++) Source.Add(i + 1);
for (int n = 0; n < N; n++)
{
int r = new Random().Next(0, Source.Count);
Result.Add(Source[r]); Source.RemoveAt(r);
}
Result.Sort();
return Result;
}
算法很好理解。好久前寫的,現(xiàn)在翻出來,一眼看出有問題。不過有點(diǎn)問題正好,看看單元測(cè)試能否找出來。
先添一個(gè)項(xiàng)目,引用NUnit.Framework,裝好NUnit后在Net組件里有,免安裝版的在解壓后的目錄里找。
新建一個(gè)Public類用于測(cè)試,叫Test,生成隨機(jī)數(shù)的方法的類叫Program。現(xiàn)在無所謂,正式項(xiàng)目里命名得規(guī)范一點(diǎn)。Test類加[TestFixture]特性,添加一個(gè)Public函數(shù)叫做TestGetRandomNum,加上[Test]特性,這樣NUnit能認(rèn)出這個(gè)方法是用于測(cè)試的方法了。還給該函數(shù)加了一個(gè)[Category("GetRandomNum")],因?yàn)橐粋(gè)功能可能要寫幾個(gè)函數(shù)來測(cè)試,這個(gè)特性表明方法屬于測(cè)試GetRandom的方法組。
還有幾個(gè)常用的特性: [TestFixtureUp] [TestFixtureDown] [TearDown] [Setup] [Ignore] [Explicit],據(jù)說以后了解這幾個(gè)差不多了。
接著,第一個(gè)測(cè)試方法該測(cè)試什么呢?以偶寫代碼的一點(diǎn)經(jīng)驗(yàn),每個(gè)函數(shù)都會(huì)把參數(shù)驗(yàn)證放在前面,參數(shù)無效不往下走了,拋異常什么的該干嘛干嘛,那測(cè)試也先從參數(shù)測(cè)起吧。 現(xiàn)在分析一下參數(shù)異常下的輸出:若N<1,不管Max值多少都返回空的List;若N>=1,且Max<N,由于Source集合數(shù)量不夠,應(yīng)該會(huì)引發(fā)IndexOutOfRangeException。
寫一個(gè)測(cè)試方法用于測(cè)試這兩種異常輸出,應(yīng)該寫兩個(gè)測(cè)試方法好一點(diǎn)。不過剛?cè)胧,一個(gè)兩個(gè)不必分了,寫出來好。代碼如下:
1 public void TestGetRandomNum3()
2 {
3 int result1 = 0, result2 = 0, result3 = 0;
4 //N<1的case
5 int[,] case1 = { { 0, 0 }, { 9999, 0 }, { -888, 0 }, { 1111, -888 }, { 0, -1 }, { -100, -99 } };
6 for (int i = 0; i < 6; i++)
7 {
8 int Max = case1[i, 0];
9 int N = case1[i, 1];
10 List<int> list = Program.GetRandomNum(Max, N);
11 if( list.Count==0) result1 ++;
12 }
13 //N>=1,Max<N
14 int[,] case2 = { { 0, 5 }, { 0, 1 }, { -10, 1 }, { -10, 30 }, { 10, 20 } };
15 for (int j = 0; j < 5; j++)
16 {
17 int Max = case2[j, 0];
18 int N = case2[j, 1];
19 try
20 {
21 List<int> list = Program.GetRandomNum(Max, N);
22 }
23 catch (IndexOutOfRangeException ex)
24 {
25 result2++;
26 }
27 }
28 //M=N>=1
29 int[,] case3 = { { 1, 1 }, { 10, 10 } };
30 for (int k = 0; k < 2; k++)
31 {
32 int Max = case3[k, 0];
33 int N = case3[k, 1];
34 List<int> list = Program.GetRandomNum(Max, N);
35 bool isMatch = true;
36 for (int n = 0; n < list.Count; n++)
37 {
38 if (n != list[n]) { isMatch = false; break; }
39 }
40 if (isMatch && list.Count == N) result3++;
41 }
42
43 Assert.AreEqual(result1, 6);
44 Assert.AreEqual(result2, 5);
45 Assert.AreEqual(result3, 2);
46 }
運(yùn)行NUnit加載項(xiàng)目,雙擊選中剛寫的方法,眼前出現(xiàn)一根長(zhǎng)長(zhǎng)的大紅條!