qileilove

          blog已經轉移至github,大家請訪問 http://qaseven.github.io/

          走進單元測試三:實戰單元測試

           前兩篇文章講解了一些關于單元測試的基本理論知識,接下來我們應該理論聯系實踐,在實踐中體會單元測試帶給我們的便利!

            環境:VS2008,2010版本!

            目錄:
            1.前言
            2.單元測試框架
            3.斷言(Assert)
            4.測試異常
            5.忽視測試
            6.數據驅動測試
            7.單元測試的利器 → Moles技術

            1.前言

            一個完整的測試必須符合以下幾點:

            A)  考慮到各種情況,準備測試所需要的各種數據,這一步是測試的關鍵所在!

            B)  調用要測試的方法!

            C)  驗證被測試方法的行為跟預期的是否一致!

            D)  完成驗證測試之后清理各種資源!

            2.單元測試框架

            測試框架的DLL文件名為: Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll

            在VS自動創建單元測試項目就會自動引用這個DLL了!

            測試類的基本結構如圖:

            基本的測試類結構就是這樣的!

            3.斷言(Assert)

            在單元測試代碼里斷言是無處不在的,我們應該合理的使用斷言來驗證數據!

            它是一個靜態類,主要有下面幾種方法用來驗證函數的結果跟我的預期是否一致!

            ① Assert.AreEqual

            主要是驗證函數產生的影響值或返回的值跟預期是否一致,這個方法不適合驗證返回的數據集以及集合之類的數據,主要針對字符串,數字等等的單一類型,它還有個泛型重載,這個是比較好的,建議多使用,它還有第三個參數,是一個string型的message,基本上不會用到!

            ☆ Note:不要把參數的含義搞混,第一個參數是你的期望值(Except),第二個參數是函數返回或影響程序產生的實際值(Actual),不要把兩個顛倒過來,因為如果運行正確沒有什么大礙,如果運行產生錯誤,有的時候就會看錯掉,造成判斷失誤,要注意了,這是一個規范!

            例子:

            Assert.AreEqual<string>("a", "a", "cheng xu yuan");

            ② Assert.AreNotEqual

            沒什么要講的,情況跟上面相反,主要是驗證實際值跟期望值不相等的情況!

          ③ Assert.AreSame

            判斷實際值跟預期值的類型是否一致!

            ④ Assert.AreNotSame

            跟上面正好相反,測試類型不一致!

            ⑤ Assert.IsNotNull,Assert.IsNull,Assert.IsTrue,Assert.IsFalse

            看這些方法名就知道什么意思了!

            ⑥ Assert.IsInstanceOfType,Assert.IsNotInstanceOfType

            判斷指定的對象是否是指定的類型!

            ⑦ Assert.Fail

            迫使斷言失敗,不管前面的斷言是否都成功了,但測試結果是錯誤的,因為我強制斷言失敗了!

            總結:一個好的測試案例,里面的斷言至少是大于一個的,這樣才能驗證數據的準確性,保證驗證數據的嚴謹性!

            例:如果實際值是個DataSet一般測試流程為:①判斷是否為“null” → ②判斷是否為“Empty”(驗證是否有數據) →③ 接下來再驗證數據的一致性,所以驗證DataSet的基本流程就是這樣的!

          /// <summary>
          /// Modify.
          /// </summary>
          [TestMethod()]
          [RollBack()]
          public void UpdateBondAssessApplicationConfiguration_ModifyData_DataUpdated() //注意命名規范,下一篇會著重講解!
          {
          AssessApplicationConfigurationDataSet assessConfigurationDataSet = target.GetBondAssessApplicationConfiguration();
          assessConfigurationDataSet.CM_LookupConfiguration[0].Description = "This is my modify";
          AssessApplicationConfigurationDataSet actual = target.UpdateBondAssessApplicationConfiguration(assessConfigurationDataSet);
          AssessApplicationConfigurationDataSet newAssessAppDataSet = target.GetBondAssessApplicationConfiguration();

          Assert.IsNotNull(actual);                                                                       //第一步 驗證是否為Null
          Assert.IsTrue(actual.CM_LookupConfiguration.Rows.Count > 0);                                    //第二步 驗證是否為Empty
          Assert.IsTrue(newAssessAppDataSet.CM_LookupConfiguration[0].Description == "This is my modify");//第三步 驗證數據的一致性
          Assert.IsTrue(CompareToTable(newAssessAppDataSet.CM_LookupConfiguration, actual.CM_LookupConfiguration));
          }

            4.測試異常 → ExpectedException(異常屬性)

            當代碼中有拋出異常的情況時,我們應該對這個異常的準確性進行測試,首先要捕獲這個異常,然后再跟我預期定義的異常進行比較就行了!

            在VS自帶的測試框架中提供了處理異常的測試!

            這個異常屬性有兩個構造函數重載:

            第一個參數:函數中出現異常的類型 →  [ExpectedException(typeof(NullReferenceException))]

            第二個參數:異常所提示的信息(Message) → [ExpectedException(typeof(NullReferenceException),"Don't is null.")]

            總結:在測試一些非法數據,邊界值,異常測試是非常有用的,一旦發現異常,后面的一切斷言和代碼將跳過,然后系統將會把異常和你預期的異常進行比對,一致則表示通過,反之有錯誤!

          /// <summary>
          /// Is null.
          /// </summary>
          [TestMethod()]
          [RollBack()]
          [ExpectedException(typeof(NullReferenceException))]  //第一種只定義了異常類型!
          public void UpdateLookupChequeNumberRegion_UpdateChequeNumberRegionAndDataSetIsNull_ThrowException()
          {
          LookupChequeNumberRegionDataSet actual = target.UpdateLookupChequeNumberRegion(null);
          }
          /// <summary>
          /// Add.
          /// </summary>
          [TestMethod()]
          [RollBack()]            //第二種定義了預期的異常類型還定義了異常信息!
          [ExpectedException(typeof(BusinessException), "The category and code combination you have entered already exist. Please enter a different category and code combination.")]
          public void UpdatePolicyConsideration_AddPolicyTheCODEIsSame_ThrowException()
          {
          string newGUID = Guid.NewGuid().ToString();
          CodeTableDataSet expectedDataSet = target.GetPolicyConsideration();
          expectedDataSet.T_IC_CODE.AddT_IC_CODERow(GetNewRow(expectedDataSet, null, ref newGUID));
          CodeTableDataSet actual = target.UpdatePolicyConsideration(expectedDataSet);
          }




          5.忽視測試 → Ignore屬性

            添加這個屬性表明現在這個測試案例在運行時將不會被執行,跳過此方法!

          [TestMethod()]
          [Ignore()]        //運行單元測試時將忽視這個測試案例
          public void GetBondDebt_InputValidClientID_RecordFound()
          {
          int clientCoreID = GetClientIDForSomeCondition();
          DebtDataSet actual = target.GetBondDebt(clientCoreID);
          Assert.IsNotNull(actual);
          Assert.IsTrue(actual.Debt.Rows.Count > 0);
          Assert.IsTrue(CompareToDataSetAndList(actual, clientCoreID));
          }

            6.數據驅動測試

            在上一篇提到過當你的數據量很大的時候,有一種解決方案是采用數據驅動測試,把我們需要用來測試的數據放在文件中,然后運行測試,讓測試代碼去讀取文件中的數據!

            其實它也有一定的局限性,所以在合理的場合中合理的使用將減輕我們的工作量,這個判斷只能給為看官去判斷了!

            當前支持Sql Server ,Oracle,CSV,XML等等文件,下面我就介紹下CSV和XML文件的使用方法!

            ①CSV作為數據文件

            我們寫一個簡單不能再簡單的的加法運算方法來作為示例:

          public int Add(int numberOne, int numberTwo)
          {
          int one = numberOne;
          int two = numberTwo;
          int three = numberOne + numberTwo;
          return three;
          }

            a) 首先要創建連接字符串,具體步驟如下:

            I,

            II,

            III,

           通過上面步驟的操作,就會進入選擇文件的界面,按照提示即可完成,當然前提你的數據文件要準備好,完成之后會出現如下代碼:

          /// <summary>
          ///Add 的測試
          ///</summary>
          [DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV",
          "|DataDirectory|\\number.csv",
          "number#csv",
          DataAccessMethod.Sequential),  //這個是連接字符串,你也可以手動寫,不要按照上面步驟操作,當然要寫對單詞和“注意文件的路徑”!
          DeploymentItem("MyTest\\number.csv"),
          TestMethod()]
          public void AddTest1()
          {
          Program target = new Program();
          int numberOne = Convert.ToInt32(this.testContextInstance.DataRow["One"]);  //獲取數據!
          int numberTwo = Convert.ToInt32(this.testContextInstance.DataRow["Two"]); ;
          int expected = Convert.ToInt32(this.testContextInstance.DataRow["Except"]);
          int actual = target.Add(numberOne, numberTwo);
          Assert.AreEqual(expected, actual);
          }

            點擊運行你的測試,程序會通過你設置的路徑去文件里面一行一行的讀取數據,然后驗證數據,如果其中有一行數據報錯,那么整個測試也就是失敗了,所以保證數據的正確性很重要!

            注意:CSV默認會以Excel的方式打開,但是它里面的數據擺放有一個規則,就是以逗號的形式呈現,所以我還是建議大家使用記事本來添加數據!

            ②使用XML作為數據文件

            其實使用方法跟上面的一樣,尤其注意的是你XML文件里面數據的格式!

          <table> //一定要設置根節點,如果不設置在文件選擇的時候會報錯!
          <my>
          <price>1</price>
          <number>1</number>
          <total>1</total>
          </my>
          <my>
          <price>2</price>
          <number>2</number>
          <total>4</total>
          </table>

            注意:怎么來獲取數據呢?Convert.ToInt32(this.testContextInstance.DataRow["price"]) 通過這樣的方式來獲取數據,還有在選擇文件時,要確認是否選中了一個數據源文件,這個不要疏忽了!

            ③使用數據庫作為數據文件很簡單,配置一下連接字符串,設置一下路徑就好了,在此就不講解了!

            7.單元測試的利器 → “Mole”技術

            首先想感謝下項目組的Tian Mi大哥是他把這項技術帶給我們的,謝謝他的無私奉獻!

            “Mole”文件的下載地址:http://www.kuaipan.cn/index.php?ac=file&oid=29568238492847207

            ①應用環境:

            所屬模塊依賴于系統的其它模塊,依賴于系統的一些配置環境,還有就是調用第三方接口或服務等等的場景!

            在這樣的場景下我們的測試是不能直接調用第三方接口或服務的,所以我們要制造一個虛擬的環境,當我們去調用接口時,Mole技術會攔截我們調用的方法,從而轉向我們自己制造的虛擬環境,那么就不會直接調用第三方接口和服務了!

            ②基本的操作流程不講解了,如果你看了http://www.cnblogs.com/hwade/archive/2010/11/26/Moles.html這篇文章就明白了,我就將一些在寫測試時遇到的幾個小問題!

            ③如果“Moles”結束后,項目編譯的時候報錯,具體的錯誤我也不怎么知道了,但是我在網上搜了很久才找到答案的!

            步驟:點擊你的Moles文件,你會發現他是個XML配置文件,修改它的屬性就好了,如:

          <Moles  xmlns=http://schemas.microsoft.com/moles/2010/  DisableCache="true" >  //增加一個DisableCache = "true"這個屬性,如果遇到問題,基本都是這個問題,這樣解決就Ok了!
          <Assembly Name="Foundation.FinanceManagement.BusinessService"  />
          </Moles>

           ③有“Ref”參數的方法應該怎么寫?

            如果參數中ref參數,那么就不能按一般的方式寫了,應該這樣寫:

            ④Moles的基本語法

            Moles的內部原理沒有明白,只懂的怎么去用它,基本的語法可以模仿上面的寫法!

            因為你把一個DLL Moles之后并編譯之后會生成一個新的DLL,這里面就是虛擬環境場所,而且類名稱都是以“M”開頭的!

            語法:命名空間 + Moles + M + 你Moles掉的類名 + Allinstance + 選擇你要攔截的方法名 = (instance(必填參數,如果方法沒參數,也必要添個))  =>

            {

            //里面寫你的邏輯,制造你自己的虛擬環境,如果方法有返回值,可以自己指定返回值的!

            };

            好了,關于在實踐中的單元測試就這么多了,其實最重要的還是你考慮測試的角度要多樣化,就是考慮問題要全面,還有代碼的簡潔性,重構,封裝等等,下一篇將是對這方面的著重討論!

          相關文章:

          走進單元測試二:測試需要從哪些方面著手

          走進單元測試四:單元測試背后的思考和感悟


          posted on 2013-08-09 10:48 順其自然EVO 閱讀(220) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          <2013年8月>
          28293031123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          導航

          統計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 三原县| 隆昌县| 武清区| 玉林市| 大厂| 铜山县| 公安县| 若尔盖县| 嵊泗县| 南丹县| 拉萨市| 古交市| 昆山市| 郴州市| 武城县| 将乐县| 郓城县| 乌兰察布市| 温泉县| 合作市| 东乡族自治县| 大同市| 墨玉县| 台中市| 富源县| 乳山市| 稷山县| 大荔县| 兰溪市| 错那县| 翁牛特旗| 长宁区| 隆德县| 石家庄市| 稻城县| 广宗县| 平昌县| 拜泉县| 丹江口市| 洪湖市| 长武县|