VS2013 單元測試(使用VS2013自帶的單元測試)

本文是官方文檔的學習筆記,官方文檔在這裏less

一、打開VS3013,隨便建一個解決方案,好比叫:LearnUnitTest,建一個類庫項目LearnUnitTest_Bank,該項目中添加一個BankAccount類,這個類及類中的方法就是咱們要測試的對象。ide

二、給LearnUnitTest添加一個測試項目:在解決方案名稱上右鍵=》添加=》新建項目=》VisualC#=》測試=》單元測試項目,項目名稱叫LearnUnitTest_BankTest,將LearnUnitTest_Bank添加爲LearnUnitTest_BankTest的引用項目,將測試項目LearnUnitTest_BankTest裏默認生成的類重命名爲BankAccountTest。函數

對於BankAccountTest類,類上有註解TestClass,方法上有註解TestMethod。能夠在這類文件裏添加其餘類和方法,供測試方法使用。單元測試

首個測試:學習

三、如今咱們測試BankAccount類的Debit方法,咱們預先肯定這次測試要檢查以下方面:測試

  a、若是信用餘額(credit amount)比帳戶餘額大,該方法就拋異常ArgumentOutOfRangeExceptionspa

  b、若是信用餘額小於0也拋異常3d

  c、若是a和b都知足,該方法會從帳戶餘額裏減去amount(函數參數)code

  注意:由a、b、c能夠看郵BankAccount類中的Debit方法最後一行應該是-=,而不是+=——固然了,這個是故意留下的bug,而不是微軟的失誤,就等着在此次測試中把它測出來,而後修正掉。對象

  

  在測試類裏添加以下方法測試Debit方法:

  

// unit test code
[TestMethod]
public void Debit_WithValidAmount_UpdatesBalance()
{
    // arrange
    double beginningBalance = 11.99;
    double debitAmount = 4.55;
    double expected = 7.44;
    BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);

    // act
    account.Debit(debitAmount);

    // assert
    double actual = account.Balance;
    Assert.AreEqual(expected, actual, 0.001, "Account not debited correctly");
}
View Code

  測試方法的要求:

  必需要有TestMethod註解,返回類型爲void,不能有參數。

通過測試,咱們發現了bug,把+=改成-=便可。

使用單元測試改善代碼:

  依然是測試Debit,本次測試想完成如下意圖:

  a、若是credit amount(指的應該就是debit amount)比balance大,方法就拋ArgumentOutOfRangeException

  b、若是credit amount比0小,也拋ArgumentOutOfRangeException異常

(1)建立測試方法

首次嘗試建立一個測試方法來處理上述問題:

代碼:

//unit test method
[TestMethod]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange()
{
    // arrange
    double beginningBalance = 11.99;
    double debitAmount = -100.00;
    BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);

    // act
    account.Debit(debitAmount);

    // assert is handled by ExpectedException
}
View Code

注意這個方法:Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange,意思是:當debit amount小於0時,本次測試應該會致使被測試的方法拋出ArgumentOutOfRange異常,不然本次測試就失敗了,沒有達到指望,須要修改Debit代碼以達成本次測試指望——正所謂TDD開發。
咱們使用了ExpectedExceptionAttribute特性來斷言指望的異常應當被拋出。除非方法拋出ArgumentOutOfRangeException異常,不然該特性就會致使測試失敗(要注意本次測試的意圖)。用正的和負的debitAmount運行這個測試,而後臨時把被測試的方法(Debit方法)修改一下:當demit amount小於0時拋出一個ApplicatinException。搗騰完這些,發現本次測試基本沒什麼問題。

爲了測試debit amount 大於balance的情形,咱們作下面幾個操做:

  a、建立一個新的測試方法名叫    Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange

  b、從上一個測試方法

 Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange

複製方法體到本測試方法

  c、把debitAmount設置爲一個比balance大的值

(2)運行測試方法

用不一樣的debitAmount值運行Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange

 Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange

而後運行三個測試,這樣咱們最開始設定的三個cases都被覆蓋了。

(3)繼續分析

後面兩個測試方法Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange

 和Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange

 有些問題:兩個測試運行的時候根據拋出的異常,你不知道是誰拋出的,靠ExpectedException特性作不到這件事。

能夠這樣修改:

在類裏定義兩個常量:

// class under test
public const string DebitAmountExceedsBalanceMessage = "Debit amount exceeds balance";
public const string DebitAmountLessThanZeroMessage = "Debit amount less than zero";

// method under test
// ...
    if (amount > m_balance)
    {
        throw new ArgumentOutOfRangeException("amount", amount, DebitAmountExceedsBalanceMessage);
    }

    if (amount < 0)
    {
        throw new ArgumentOutOfRangeException("amount", amount, DebitAmountLessThanZeroMessage);
    }
// ...
View Code

(4)重構測試方法

 首先,移除ExpectedException特性。取而代之的處理是:咱們捕獲異常,來覈實是在哪一種條件下拋出的。

修改一下Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange 

方法:

[TestMethod]
public void Debit_WhenAmountIsGreaterThanBalance_ShouldThrowArgumentOutOfRange()
{
    // arrange
    double beginningBalance = 11.99;
    double debitAmount = 20.0;
    BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);\

    // act
    try
    {
        account.Debit(debitAmount);
    }
    catch (ArgumentOutOfRangeException e)
    {
        // assert
        StringAssert.Contains(e.Message, BankAccount. DebitAmountExceedsBalanceMessage);
    }
}
View Code


(5)再次測試,再次重寫,再次分析

當咱們用不的參數再次運行測試方法Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange 

的時候,會遇到下面一些問題:

一、若是咱們使用一個比balance大的debitAmount運行,產生的測試結果是所指望的。

二、若是使用了一個debitAmount運行,使得assert 斷言失敗了(好比在Debit方法的某一行返回了一個非指望的異常),也沒什麼問題,在本測試的情理之中。

三、若是debitAmount是有效的(比0大比balance小)會發生什麼呢?沒有異常拋出,斷言也不會失敗,測試方法經過了。——這不是咱們想要的,注意咱們這次的測試初衷:要麼斷言成功,要麼斷言失敗,若是壓根進入不了斷言代碼,只能說明測試方法寫的問題!

爲了解決這個問題,咱們在測試方法的最後一行加入一個Fail斷言,來處理沒有異常發生的狀況:沒有異常發生,就說明這次測試沒有達到指望!

可是修改好再次運行,會發現若是所指望的異常被捕獲了,測試總會失敗。爲了解決這個問題,咱們在StringAssert以前加一個return。

最終咱們的Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange 

方法以下:

[TestMethod]
public void Debit_WhenAmountIsGreaterThanBalance_ShouldThrowArgumentOutOfRange()
{
    // arrange
    double beginningBalance = 11.99;
    double debitAmount = 20.0;
    BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);\

    // act
    try
    {
        account.Debit(debitAmount);
    }
    catch (ArgumentOutOfRangeException e)
    {
        // assert
        StringAssert.Contains(e.Message, BankAccount. DebitAmountExceedsBalanceMessage);
        return;
    }
    Assert.Fail("No exception was thrown.")
}
View Code


最終咱們讓測試代碼變得更增強健,但更重要的是,在這個過程當中,我也們也改善了被測試的代碼——這纔是測試的最終目的。

 

微軟接下來說的是測試驅動開發。連接以下:

測試驅動開發

相關文章
相關標籤/搜索