系列目錄 <https://www.cnblogs.com/tylerzhou/p/11204826.html>
在進(jìn)行單元測試的時候,很多時候,很多時候我們都是在單元測試方法內(nèi)部提供特定的值,但是這樣測試往往造成樣本數(shù)不足從而導(dǎo)致覆蓋的結(jié)果不夠全面,很多時候我們更想提供來自外部的,滿足條件的一組值來進(jìn)行測試.其實Nunit框架本身提供了為測試用例提供值的能力.我們可以對它進(jìn)行擴(kuò)展來實現(xiàn)導(dǎo)入外部的值來填充到測試方法內(nèi)部.很多朋友也自己寫了不少按照一定規(guī)則生成值的方法.但是往往都是在方法內(nèi)部直接調(diào)用,這樣就會和單元測試的邏輯混雜在一塊,導(dǎo)致測試方法本身不夠簡潔.其實可以根本測試框架本身的能力改造成為注解的方式,這樣參數(shù)生成邏輯和測試邏輯一目了然.后面我們還會講解基于Autofixture框架來生成填充數(shù)據(jù),autofixture相比我們自己寫的值填充方法,往往功能更加強(qiáng)大.后面我們將見證其強(qiáng)大之處.
提供普通參數(shù)
很容易發(fā)現(xiàn),單元測試的方法都是不帶參數(shù)的,有些時候我們需要為一個要測試的方法(并非單元測試方法)提供多個參數(shù)進(jìn)行測試,這就會導(dǎo)致一個問題:我們需要寫很多類似的測試方法,只是參數(shù)不一樣,這樣維護(hù)起來不方便,同時大量重復(fù)的工作也很煩.下面介紹Nunit里如何為測試提供參數(shù)
int Add(int x, int y) { return x + y; }
以上是我們要測試的方法.
雖然Nunit測試方法正常情況下是不支持參數(shù)的,但是如果對參數(shù)添加的values注解,Nunit便會把這些參數(shù)應(yīng)用到測試.
我們看一下編寫的測試方法
[Test] public void DemoTest([Values(3,4,5)]int a,[Values(6,7,8)]int b) { var
result = Add(a, b); Assert.AreEqual(a + b, result); }
我們運(yùn)行以上方法,可以看到測試結(jié)果通過,但是我們看一下測試面板(Test Explorer)
通過截圖我們很容易發(fā)現(xiàn),這個測試方法一共運(yùn)行的九次!再仔細(xì)看看方法對應(yīng)的參數(shù),可以看到它是使用組合的方式把所有的可能都組合一遍.
但是有些時候我們想要的不是這樣的組合,我們想要的更多時候是(3,6),(4,7),(5,8)這樣的組合,如何做到呢,仍然看一段示例代碼
[Test] [Sequential] public void DemoTest([Values(3,4,5)]int
a,[Values(6,7,8)]int b) { var result = Add(a, b); Assert.AreEqual(a + b,
result); }
我們看看運(yùn)行結(jié)果
這次只運(yùn)行了三次,并且參數(shù)的組合正如我們期待的.
這個方法和上面的一樣,只是多了一個[Sequential]注解
注意Values注解里的參數(shù)都是Object類型,運(yùn)行時候轉(zhuǎn)換為參數(shù)的真正類型,如果無法轉(zhuǎn)換則會拋出異常.比如[Values("a")]int x
由于a是字符串類型,通過內(nèi)置方法無法轉(zhuǎn)換為int,因些會拋出異常.
提供基于范圍的參數(shù)
上面的測試Values(3,4,5)和Values(6,7,8)都是連續(xù)的數(shù)字,如果連接的參數(shù)更多,我們可以使用基于范圍的參數(shù).
看以下示例代碼
[Test] [Sequential] public void DemoTest([Range(3,5)]int a,[Range(6,8)]int b)
{ var result = Add(a, b); Assert.AreEqual(a + b, result); }
我們把Values注解改為Range注解,就ok了
提供隨機(jī)參數(shù)
我們還可以為測試提供一些隨機(jī)數(shù),以使測試變得更隨機(jī),覆蓋范圍更大
這里要使用Random注解
請看下面示例
[Test] [Sequential] public void DemoTest([Random(3)]int a, [Random(3)]int b)
{ var result = Add(a, b); Assert.AreEqual(a + b, result); }
Random的參數(shù)為要生成隨機(jī)數(shù)的個數(shù).
Random還有一重載以支持生成隨機(jī)數(shù)的最大值和最小值
[Test] [Sequential] public void DemoTest([Random(3,10,2)]int a,
[Random(5,9,3)]int b) { var result = Add(a, b); Assert.AreEqual(a + b, result);
}
示例中Random的三個參數(shù)分別是最小值,最大值和個數(shù)
[info]Random的最大值和最小值不僅可以是整數(shù),也可以是小數(shù)
提供計算參數(shù)
先看一個示例
[Test] [Sequential] public void DemoTest(DateTime dt1) { DateTime dt2 =
default(DateTime); Assert.Greater(dt1, dt2); }
這里測試方法的參數(shù)是Datetime類型,我們?nèi)绾谓o給它提供值呢,很多人可能會想使用Values[DateTime.Now]
來注解dt1參數(shù),然而不幸的是Values注解只接受const類型的值,這里介紹ValueSource注解來解決這個問題.
ValueSource的機(jī)制是使用一個方法來獲取值,然后提供給測試方法參數(shù),它接受一個字符串類型的參數(shù),用于指定提供值的方法名.
我們用以下方法生成一些DateTime值
static IEnumerable<DateTime> GetPeople() { yield return DateTime.Now; yield
return DateTime.Now.AddDays(2); }
以上方法生成了一個包含兩個DateTime值的集合.下面我們看如何使用它
[Test] public void
DemoTest([ValueSource(nameof(FirstUnitTest.GetPeople))]DateTime dt1) { DateTime
dt2 = default(DateTime); Assert.Greater(dt1, dt2); }
我們使用nameof獲取剛才生成的用于提供值的方法,作為ValueSource的參數(shù).
使用nameof而不是使用手寫字符串的好處在于nameof可以有智能提示,防止手寫出現(xiàn)錯誤,另外就是如果方法名更改,這里將會拋出了一個錯誤,靜態(tài)字符串不會提示錯誤,如果在運(yùn)行時找不到這個方法則會拋出運(yùn)行時錯誤
用于為ValueSource提供值的方法必須是靜態(tài)的
以上代碼,我們把提供值的方法直接寫在測試類里,這并不是一種很好的實踐,一種好的做法是把所有的用于提供值的方法放在一個外部的類中.
我們把這個類移動到一個叫作MyValueProvider的類中
代碼如下
public class MyValueProvider { public static IEnumerable<DateTime> GetPeople()
{ yield return DateTime.Now; yield return DateTime.Now.AddDays(2); } }
單元測試方法改成如下:
[Test] public void
DemoTest([ValueSource(typeof(MyValueProvider),nameof(MyValueProvider.GetPeople))]DateTime
dt1) { DateTime dt2 = default(DateTime); Assert.Greater(dt1, dt2); }
如果把值提供方法不在本類中(當(dāng)前測試方法所在的類),提供一個Type類型(提供值的方法所在的類的類型)作為第一個參數(shù),方法名作為第二個參數(shù).
上面講的都是基于參數(shù)注解的值提供方法,這里基于方法的注解的值提供方法.當(dāng)然,它完成的功能基于參數(shù)注解的方法也同樣能完成.
TestCaseAttribute注解
看以下代碼片段
[TestCase(3,4)] public void DemoTest(int x,int y) { var val = Add(x, y);
Assert.AreEqual(x + y, val); }
其中用到的Add方法代碼如下
int Add(int x, int y) { return x + y; }
TestCase的工作原理是這樣的,它提供的值是基于位置的,每一個位置處的值賦值給第一個參數(shù),第二個位置處的值提供給第二個參數(shù)...
有了TestCase注解之后,Test注解不再是必要的.
TestCaseSourceAttribute注解
從上ValueSource我們很容易想到可能會有TestCaseSource,實際上也確實是這樣的,TestCaseSource功能也同ValueSource一樣,用于提供基于計算的結(jié)果.
用于提供值的類如下
public class MyValueProvider { public static ArrayList ar = new ArrayList {
new int[] {3, 4}, new int[] {5, 9}, new int[] {9, 22} }; }
測試方法如下
[TestCaseSource(typeof(MyValueProvider),nameof(MyValueProvider.ar))] public
void DemoTest(int x,int y) { var val = Add(x, y); Assert.AreEqual(x + y, val); }
從這個例子我們可看到,不僅方法可以提供值,屬性,普通字段也可以提供值
為TestCaseSource提供值的字段,方法,屬性也必須是靜態(tài)的
TestCase和TestCaseSource都支持多重注解,有幾個注解,測試方法就會運(yùn)行幾次.
熱門工具 換一換
感谢您访问我们的网站,您可能还对以下资源感兴趣:
调教肉文小说-国产成本人片免费av-空姐av种子无码-在线观看免费午夜视频-综合久久精品激情-国产成人丝袜视频在线观看软件-大芭区三区四区无码-啊啊好爽啊啊插啊用力啊啊-wanch视频网-国产精品成人a免费观看