qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請訪問 http://qaseven.github.io/

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

           1、打開VS3013,隨便建一個解決方案,比如叫:LearnUnitTest,建一個類庫項目LearnUnitTest_Bank,該項目中添加一個BankAccount類,這個類及類中的方法就是我們要測試的對象。
            2、給LearnUnitTest添加一個測試項目:在解決方案名稱上右鍵=》添加=》新建項目=》VisualC#=》測試=》單元測試項目,項目名稱叫LearnUnitTest_BankTest,將LearnUnitTest_Bank添加為LearnUnitTest_BankTest的引用項目,將測試項目LearnUnitTest_BankTest里默認生成的類重命名為BankAccountTest。
            對于BankAccountTest類,類上有注解TestClass,方法上有注解TestMethod。可以在這類文件里添加其他類和方法,供測試方法使用。
            首個測試:
            3、現(xiàn)在我們測試BankAccount類的Debit方法,我們預(yù)先確定此次測試要檢查如下方面:
            a、如果信用余額(credit amount)比賬戶余額大,該方法就拋異常ArgumentOutOfRangeException
            b、如果信用余額小于0也拋異常
            c、如果a和b都滿足,該方法會從賬戶余額里減去amount(函數(shù)參數(shù))
            注意:由a、b、c可以看郵BankAccount類中的Debit方法最后一行應(yīng)該是-=,而不是+=——當然了,這個是故意留下的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");
          }
            測試方法的要求:
            必須要有TestMethod注解,返回類型為void,不能有參數(shù)。
            經(jīng)過測試,我們發(fā)現(xiàn)了bug,把+=改為-=即可。
            使用單元測試改善代碼:
            依然是測試Debit,本次測試想完成以下意圖:
            a、如果credit amount(指的應(yīng)該就是debit amount)比balance大,方法就拋ArgumentOutOfRangeException
            b、如果credit amount比0小,也拋ArgumentOutOfRangeException異常
            (1)創(chuàng)建測試方法
            首次嘗試創(chuàng)建一個測試方法來處理上述問題:
            代碼:
          //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
          }
            注意這個方法:Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange,意思是:當debit amount小于0時,本次測試應(yīng)該會導(dǎo)致被測試的方法拋出ArgumentOutOfRange異常,否則本次測試就失敗了,沒有達到期望,需要修改Debit代碼以達成本次測試期望——正所謂TDD開發(fā)。
            我們使用了ExpectedExceptionAttribute特性來斷言期望的異常應(yīng)當被拋出。除非方法拋出ArgumentOutOfRangeException異常,否則該特性就會導(dǎo)致測試失敗(要注意本次測試的意圖)。用正的和負的debitAmount運行這個測試,然后臨時把被測試的方法(Debit方法)修改一下:當demit amount小于0時拋出一個ApplicatinException。搗騰完這些,發(fā)現(xiàn)本次測試基本沒什么問題。
            為了測試debit amount 大于balance的情形,我們做下面幾個操作:
            a、創(chuàng)建一個新的測試方法名叫    Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange
            b、從上一個測試方法
            Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange
            復(fù)制方法體到本測試方法
            c、把debitAmount設(shè)置為一個比balance大的值
            (2)運行測試方法
            用不同的debitAmount值運行Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange
            和 Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange
            然后運行三個測試,這樣我們最開始設(shè)定的三個cases都被覆蓋了。
           (3)繼續(xù)分析
            后面兩個測試方法Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange
            和Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange
            有些問題:兩個測試運行的時候根據(jù)拋出的異常,你不知道是誰拋出的,靠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);
          }
          // ...
            (4)重構(gòu)測試方法
            首先,移除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);
          }
          }
            (5)再次測試,再次重寫,再次分析
            當我們用不的參數(shù)再次運行測試方法Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange
            的時候,會遇到下面一些問題:
            1、如果我們使用一個比balance大的debitAmount運行,產(chǎn)生的測試結(jié)果是所期望的。
            2、如果使用了一個debitAmount運行,使得assert 斷言失敗了(比如在Debit方法的某一行返回了一個非期望的異常),也沒什么問題,在本測試的情理之中。
            3、如果debitAmount是有效的(比0大比balance小)會發(fā)生什么呢?沒有異常拋出,斷言也不會失敗,測試方法通過了。——這不是我們想要的,注意我們此次的測試初衷:要么斷言成功,要么斷言失敗,如果壓根進入不了斷言代碼,只能說明測試方法寫的問題!
            為了解決這個問題,我們在測試方法的最后一行加入一個Fail斷言,來處理沒有異常發(fā)生的情況:沒有異常發(fā)生,就說明此次測試沒有達到期望!
            但是修改好再次運行,會發(fā)現(xiàn)如果所期望的異常被捕獲了,測試總會失敗。為了解決這個問題,我們在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.")
          }
            最終我們讓測試代碼變得更加強健,但更重要的是,在這個過程中,我也們也改善了被測試的代碼——這才是測試的最終目的。

          posted on 2014-09-16 09:51 順其自然EVO 閱讀(1346) 評論(0)  編輯  收藏 所屬分類: 測試學(xué)習(xí)專欄

          <2014年9月>
          31123456
          78910111213
          14151617181920
          21222324252627
          2829301234
          567891011

          導(dǎo)航

          統(tǒng)計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 木里| 金溪县| 加查县| 阳西县| 遂宁市| 安龙县| 霸州市| 黄梅县| 宿州市| 阜平县| 太仆寺旗| 大埔县| 且末县| 乌鲁木齐县| 乌拉特中旗| 彭州市| 班戈县| 水富县| 巴青县| 中方县| 鱼台县| 岚皋县| 宽甸| 泽普县| 内乡县| 漠河县| 佛教| 惠州市| 宣化县| 卢氏县| 鄂托克前旗| 平谷区| 资中县| 娱乐| 安义县| 犍为县| 聂荣县| 体育| 吴桥县| 高碑店市| 东宁县|