系列目錄html
在進行單元測試的時候,不少時候,不少時候咱們都是在單元測試方法內部提供特定的值,可是這樣測試每每形成樣本數不足從而致使覆蓋的結果不夠全面,不少時候咱們更想提供來自外部的,知足條件的一組值來進行測試.其實Nunit框架自己提供了爲測試用例提供值的能力.咱們能夠對它進行擴展來實現導入外部的值來填充到測試方法內部.不少朋友也本身寫了很多按照必定規則生成值的方法.可是每每都是在方法內部直接調用,這樣就會和單元測試的邏輯混雜在一塊,致使測試方法自己不夠簡潔.其實能夠根本測試框架自己的能力改形成爲註解的方式,這樣參數生成邏輯和測試邏輯一目瞭然.後面咱們還會講解基於Autofixture框架來生成填充數據,autofixture相比咱們本身寫的值填充方法,每每功能更增強大.後面咱們將見證其強大之處.框架
很容易發現,單元測試的方法都是不帶參數的,有些時候咱們須要爲一個要測試的方法(並不是單元測試方法)提供多個參數進行測試,這就會致使一個問題:咱們須要寫不少相似的測試方法,只是參數不同,這樣維護起來不方便,同時大量重複的工做也很煩.下面介紹Nunit裏如何爲測試提供參數dom
int Add(int x, int y) { return x + y; }
以上是咱們要測試的方法.ide
雖然Nunit測試方法正常狀況下是不支持參數的,可是若是對參數添加的values註解,Nunit便會把這些參數應用到測試.
咱們看一下編寫的測試方法單元測試
[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); }
咱們運行以上方法,能夠看到測試結果經過,可是咱們看一下測試面板(Test Explorer)測試
經過截圖咱們很容易發現,這個測試方法一共運行的九次!再仔細看看方法對應的參數,能夠看到它是使用組合的方式把全部的可能都組合一遍.code
可是有些時候咱們想要的不是這樣的組合,咱們想要的更多時候是(3,6),(4,7),(5,8)這樣的組合,如何作到呢,仍然看一段示例代碼htm
[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); }
咱們看看運行結果blog
此次只運行了三次,而且參數的組合正如咱們期待的.
這個方法和上面的同樣,只是多了一個[Sequential]
註解字符串
注意Values註解裏的參數都是Object類型,運行時候轉換爲參數的真正類型,若是沒法轉換則會拋出異常.好比
[Values("a")]int x
因爲a是字符串類型,經過內置方法沒法轉換爲int,因些會拋出異常.
上面的測試Values(3,4,5)和Values(6,7,8)都是連續的數字,若是鏈接的參數更多,咱們可使用基於範圍的參數.
看如下示例代碼
[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了
咱們還能夠爲測試提供一些隨機數,以使測試變得更隨機,覆蓋範圍更大
這裏要使用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的參數爲要生成隨機數的個數.
Random還有一重載以支持生成隨機數的最大值和最小值
[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的三個參數分別是最小值,最大值和個數
[info]Random的最大值和最小值不只能夠是整數,也能夠是小數
先看一個示例
[Test] [Sequential] public void DemoTest(DateTime dt1) { DateTime dt2 = default(DateTime); Assert.Greater(dt1, dt2); }
這裏測試方法的參數是Datetime類型,咱們如何給給它提供值呢,不少人可能會想使用Values[DateTime.Now] 來註解dt1參數,然而不幸的是Values註解只接受const
類型的值,這裏介紹ValueSource
註解來解決這個問題.
ValueSource的機制是使用一個方法來獲取值,而後提供給測試方法參數,它接受一個字符串類型的參數,用於指定提供值的方法名.
咱們用如下方法生成一些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的參數.
使用nameof而不是使用手寫字符串的好處在於nameof能夠有智能提示,防止手寫出現錯誤,另外就是若是方法名更改,這裏將會拋出了一個錯誤,靜態字符串不會提示錯誤,若是在運行時找不到這個方法則會拋出運行時錯誤
用於爲ValueSource提供值的方法必須是
靜態的
以上代碼,咱們把提供值的方法直接寫在測試類裏,這並非一種很好的實踐,一種好的作法是把全部的用於提供值的方法放在一個外部的類中.
咱們把這個類移動到一個叫做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); }
若是把值提供方法不在本類中(當前測試方法所在的類),提供一個Type類型(提供值的方法所在的類的類型)做爲第一個參數,方法名做爲第二個參數.
上面講的都是基於參數註解的值提供方法,這裏基於方法的註解的值提供方法.固然,它完成的功能基於參數註解的方法也一樣能完成.
看如下代碼片斷
[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的工做原理是這樣的,它提供的值是基於位置的,每個位置處的值賦值給第一個參數,第二個位置處的值提供給第二個參數...
有了TestCase註解以後,Test註解再也不是必要的.
從上ValueSource咱們很容易想到可能會有TestCaseSource,實際上也確實是這樣的,TestCaseSource功能也同ValueSource同樣,用於提供基於計算的結果.
用於提供值的類以下
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提供值的字段,方法,屬性也
必須是靜態的
TestCase和TestCaseSource都支持多重註解,有幾個註解,測試方法就會運行幾回.