《電子技術應用》
您所在的位置:首頁 > 測試測量 > 設計應用 > 數(shù)據(jù)驅動測試在Nunit框架中的應用
數(shù)據(jù)驅動測試在Nunit框架中的應用
來源:微型機與應用2012年第22期
王 敏1, 陳亞光2
(1. 武昌理工學院 信息工程學院, 湖北 武漢 430223; 2. 中南民族大學 生物醫(yī)學工程學
摘要: 為了解決單元測試工具Nunit本身不支持數(shù)據(jù)驅動測試的問題,提出了在Nunit框架下實現(xiàn)數(shù)據(jù)驅動測試的方法。該方法首先將測試類所使用的測試數(shù)據(jù)基本信息設定在ini文件中,將輸入數(shù)據(jù)及預期結果存放于Excel文件中。隨后通過屬性標簽[TestFixtureSetUp]標記的方法動態(tài)讀取ini文件中的基本信息,再根據(jù)這些基本信息讀取Excel文件中的測試數(shù)據(jù),并將測試數(shù)據(jù)保存于自定義的結構體數(shù)組中供各測試方法使用。該方法有效地實現(xiàn)了測試數(shù)據(jù)與測試腳本的分離,能降低測試腳本的維護工作量,提高測試效率。
Abstract:
Key words :

摘  要: 為了解決單元測試工具Nunit本身不支持數(shù)據(jù)驅動測試的問題,提出了在Nunit框架下實現(xiàn)數(shù)據(jù)驅動測試的方法。該方法首先將測試類所使用的測試數(shù)據(jù)基本信息設定在ini文件中,將輸入數(shù)據(jù)及預期結果存放于Excel文件中。隨后通過屬性標簽[TestFixtureSetUp]標記的方法動態(tài)讀取ini文件中的基本信息,再根據(jù)這些基本信息讀取Excel文件中的測試數(shù)據(jù),并將測試數(shù)據(jù)保存于自定義的結構體數(shù)組中供各測試方法使用。該方法有效地實現(xiàn)了測試數(shù)據(jù)與測試腳本的分離,能降低測試腳本的維護工作量,提高測試效率。
關鍵詞: 單元測試; Nunit框架; 測試腳本; 測試數(shù)據(jù)

    軟件測試是保證軟件質量的重要手段,作為軟件測試基礎的單元測試是軟件開發(fā)過程中最低級的測試活動。據(jù)業(yè)界統(tǒng)計,單元測試一般可以發(fā)現(xiàn)大約80%的軟件缺陷[1]。由于軟件缺陷發(fā)現(xiàn)得越早,其修復的代價就越小,因此,單元測試在軟件測試過程中占據(jù)著非常重要的地位,有效地實施單元測試能有效節(jié)約后續(xù)測試時間、降低測試成本、保證軟件質量。
    Nunit是微軟.Net平臺下的單元測試框架,也是在.Net平臺下進行測試驅動開發(fā)的重要工具;其提供的圖形用戶接口GUI操作簡單、內容直觀,因此Nunit被廣泛地運用于.Net平臺項目的單元測試中。利用Nunit進行單元測試,首先要進行腳本開發(fā),目前常用的方法是將測試數(shù)據(jù)以常量的方式賦值給變量,再由變量參與測試[2-3]。采用這種方式,測試數(shù)據(jù)與測試腳本共存于一個測試腳本文件中,不利于測試腳本的維護。而測試腳本的維護是自動化測試的重要環(huán)節(jié),適當?shù)卣{整和增強測試腳本,能提高測試腳本的靈活性以及應對測試對象變更的能力,數(shù)據(jù)驅動方式的測試腳本開發(fā)是解決這類問題的重要手段[4]。由于Nunit框架本身并不具備數(shù)據(jù)驅動測試的功能,因此需要通過增強測試腳本的功能來實現(xiàn)Nunit框架下的數(shù)據(jù)驅動測試。為此,本文提出一種測試設計方法,將測試用例的輸入數(shù)據(jù)、預期結果及執(zhí)行條件編寫在Excel工作簿中,工作簿中每一個工作表的數(shù)據(jù)對應一個測試類;工作簿存放的位置、測試類對應的工作表名、輸入數(shù)據(jù)數(shù)目及預期結果數(shù)目等信息按一定格式保存于執(zhí)行路徑下的ini文件中。在測試腳本中,利用Nunit的[TestFixtureSetUp]屬性標簽,在該標簽標記的方法中實現(xiàn)測試類所有測試數(shù)據(jù)的一次性讀入,并將其保存于自定義的結構體數(shù)組中,供各測試方法使用,在后續(xù)測試方法的腳本編寫中,只需按結構體數(shù)組下標獲取測試數(shù)據(jù)及預期結果便能完成測試腳本的開發(fā);測試執(zhí)行時將按照Excel文件中設計的數(shù)據(jù)自動執(zhí)行測試腳本。這一測試設計方法能有效地分離測試腳本和測試數(shù)據(jù),從而降低測試腳本的維護工作量。
1 數(shù)據(jù)驅動測試的設計思路
    數(shù)據(jù)驅動測試是一種數(shù)據(jù)被包含在輸入測試數(shù)據(jù)文件中,并且以數(shù)據(jù)來控制自動化測試腳本執(zhí)行的流程和動作的測試[5]。在Nunit框架中,[TestFixtureSetUp]和[SetUp]屬性標簽標記的方法分別在測試類和各測試方法執(zhí)行前被執(zhí)行,[Test]屬性標簽標記的方法按其在腳本中的先后順序自動執(zhí)行;此外,通過Nunit的GUI界面,可以指定被執(zhí)行的方法,因此Nunit自身已經(jīng)具備控制測試腳本執(zhí)行流程的功能。這里主要從用數(shù)據(jù)驅動腳本的動作出發(fā)來實現(xiàn)數(shù)據(jù)驅動測試。
  數(shù)據(jù)驅動測試使用存檔的測試數(shù)據(jù)來驅動自動化測試過程,這些數(shù)據(jù)通常以簡單的文本文件或Excel文件形式存在[5]。鑒于Excel文件具有以表格形式呈現(xiàn)、結構清晰直觀的特點,本文采用Excel的工作表來存儲測試數(shù)據(jù)。同時,為使測試腳本具有較高的靈活性,將測試數(shù)據(jù)文件的存取路徑、測試數(shù)據(jù)所在的工作表名等信息存放于ini文件中,以便在測試環(huán)境和數(shù)據(jù)發(fā)生改變時,測試腳本可以保持不變,從而降低測試腳本的維護成本。
1.1 Excel文件格式的設計
    圖1為Excel文件結構與測試類及測試方法之間的對應關系圖,圖中的數(shù)據(jù)是根據(jù)Nunit自帶的一個實例Moneybag類所做的部分測試數(shù)據(jù)。

    圖1中,工作簿Moneytest.xls中的工作表Moneytest用來存放測試類Moneytest中各測試方法所需的數(shù)據(jù)。由于各測試方法常常使用一些公共的輸入數(shù)據(jù)來進行測試驗證,因此將公共數(shù)據(jù)設定在第一行,從第二行數(shù)據(jù)開始每一行數(shù)據(jù)對應一個測試方法,每一個單元格存放一個基本數(shù)據(jù)(字符串類型或數(shù)值)。結構數(shù)據(jù)類型都可以看成是基本數(shù)據(jù)類型的組合,一個結構數(shù)據(jù)類型可分成多個單元格來存放。由于每一個測試方法所需的輸入和預期值數(shù)目各不相同,在測試數(shù)據(jù)設計時,可按需要增減工作表列的數(shù)目來增減輸入和預期值的數(shù)目(圖1中3~6行的A-H列為空,是因為3~6行對應的測試方法全部采用公共輸入數(shù)據(jù))。測試數(shù)據(jù)的最后一列為測試說明,用于對測試條件等輔助信息加以說明,以供測試人員或維護人員參考,測試腳本不讀取該列數(shù)據(jù)。
1.2 ini文件的設計
    使用ini文件是為了使這一實現(xiàn)方法具有較高的靈活性,最大限度地減少因測試環(huán)境和測試數(shù)據(jù)的變化帶來的測試腳本的維護工作量。這里約定ini文件以標記的測試類命名,并且保存于執(zhí)行文件所在目錄下,這樣可通過編程來動態(tài)讀取路徑。因此,除了ini文件名外,其他所有數(shù)據(jù)的來源都是通過測試腳本執(zhí)行動態(tài)獲取的,這一實現(xiàn)方法能達到較高程度的測試腳本與測試數(shù)據(jù)的分離。
    ini文件設計如下:
     [FILE]
          path= "D:\NUNIT\Moneytest.xls"
          sheet= [Moneytest$]
     [DATA]
          input=8
          except=4
     [ROWS]
          Common=0
          BagSimpleAdd=1
          BagSubtract=2
          BagMultiply=3
        BagNegate=4
    節(jié)[FILE]用于存放Excel數(shù)據(jù)文件信息,參數(shù)path的值表示數(shù)據(jù)文件存放的路徑,參數(shù)sheet的值表示測試數(shù)據(jù)所在的工作表名;節(jié)[DATA]用于存放輸入數(shù)據(jù)和預期值的數(shù)目,這里按該測試類中使用輸入數(shù)據(jù)和預期值數(shù)目最多的方法進行設置,用于動態(tài)定義結構體內數(shù)組的維數(shù),這樣定義會損失一定的數(shù)組空間,但給測試腳本的編寫帶來了方便;節(jié)[ROWS]用于存放每個測試方法對應的測試數(shù)據(jù)所在的行編號(結構體數(shù)組下標),在各測試方法中通過讀取ini文件中的行編號來取得對應的測試數(shù)據(jù),Common=0表示將公用數(shù)據(jù)設在數(shù)據(jù)表第一行,讀入到下標為0的數(shù)組中。
2 數(shù)據(jù)驅動測試的實現(xiàn)
    Nunit采用屬性標簽來標記測試類和方法,其中[TestFixture]用于標記測試類,[Test]、[SetUp]、[TestFixtureSetUp]用于標記測試方法。[SetUp]標記的方法是為了避免代碼的冗余,該方法將各測試方法中的重復代碼提取出來,組織成一個共用的方法,在每個[Test]標記的測試方法執(zhí)行前被執(zhí)行一次,與它成對使用的是[TearDown]屬性,用來釋放[SetUp]中初始化的變量。[TestFixtureSetUp]與[SetUp]屬性類似,但此屬性標記的方法用來實現(xiàn)整個測試類的初始化,它在整個測試類執(zhí)行前執(zhí)行一次,與它成對使用的是[TestFixtureTearDown]屬性,用來釋放[TestFixtureSetUp]中初始化的變量。
    在本設計中,測試數(shù)據(jù)被存儲在外部數(shù)據(jù)文件中,每一個方法執(zhí)行前都需要外部文件中的測試數(shù)據(jù),如果將讀取外部文件的操作分別寫到各個測試方法中,這無疑會產(chǎn)生大量冗余代碼,也會增加I/O方面的開銷;如果將這部分處理寫到[SetUp]屬性方法中,可減少測試腳本中重復代碼的數(shù)量,但I/O方面的開銷與前一種方法相比,沒有任何改善。故本設計將測試數(shù)據(jù)讀取的代碼編寫在[TestFixtureSetUp]屬性標記的方法中,通過自定義一個結構體,將測試數(shù)據(jù)一次性讀出并存放于結構體數(shù)組中,即在整個測試類的方法執(zhí)行之前執(zhí)行一次測試數(shù)據(jù)的讀取操作。這樣,既能減少測試腳本中重復代碼的數(shù)量,也能減少I/O方面的開銷。
2.1 自定義結構體的實現(xiàn)
    public struct testdata
       {
                public string[] strIn ;
                public string[] strExcept;
       }
       上面是采用C#定義的結構體testdata,其中包含兩個字符串類型的動態(tài)數(shù)組,分別用來存放各測試方法的輸入數(shù)據(jù)和預期結果。因為測試類最大的輸入數(shù)據(jù)和預期結果數(shù)目在測試用例維護時可能發(fā)生變化,故采用定義動態(tài)數(shù)組的方式。
2.2 測試類初始化的實現(xiàn)
    [TestFixtureSetUp]屬性標記的方法用于整個測試類的初始化,其處理流程設計如圖2所示。

    過程①中讀取[FILE]和[DATA]節(jié)中的值,用于定位測試數(shù)據(jù)文件和定義結構體數(shù)組維數(shù);過程②按行列依次循環(huán),將數(shù)據(jù)表中的數(shù)據(jù)依次全部讀入結構體數(shù)組;過程③初始化各測試方法的公用數(shù)據(jù),下面是按照本文提出的方法,以Nunit自帶的樣例測試腳本MoneyTest.cs為例對公共輸入數(shù)據(jù)進行設定的相關代碼:
    f12CHF = new Money(Convert.ToInt32(tdTest[i].strIn[0]), tdTest[i].strIn[1]);
    f7USD = new Money(Convert.ToInt32(tdTest[i].strIn[2]), tdTest[i].strIn[3]);
    f14CHF = new Money(Convert.ToInt32(tdTest[i].strIn[4]), tdTest[i].strIn[5]);
    f21USD = new Money(Convert.ToInt32(tdTest[i].strIn[6]), tdTest[i].strIn[7]);
    fMB1 = new MoneyBag(f12CHF, f7USD);
    fMB2 = new MoneyBag(f14CHF, f21USD);
    如果約定下標為0的結構體數(shù)組中存放公共測試數(shù)據(jù),則在上面的代碼前可直接將i賦值為0,也可讀取ini文件的Common值來設定i值。
2.3 自定義方法的實現(xiàn)
    每一個方法執(zhí)行之前都需要讀取結構體數(shù)組中對應行的數(shù)據(jù),雖然讀取數(shù)據(jù)的代碼可以寫在各測試方法中,但這無疑會產(chǎn)生重復代碼。通過分析各測試方法讀取數(shù)據(jù)的相似部分,可將這部分代碼寫成一個公用方法,[SetUp]中定義的方法能保證各方法執(zhí)行之前自動執(zhí)行一次,但是該方法不能帶參數(shù)。因此,這里自定義一個帶參數(shù)的方法供各測試方法調用。同樣以Moneybag類的測試為例,該測試類中,各方法的輸入基本采用公共數(shù)據(jù),各方法的預期結果各不相同,因此各方法均有一個讀取預期結果的公共處理,將這部分處理用自定義方法實現(xiàn),參數(shù)i為各方法對應的測試數(shù)據(jù)的數(shù)組下標。代碼如下:
    private void SetValue(int i)
    {
    mexcept1 = new Money(Convert.ToInt32(tdTest[i].strExcept[0]), tdTest[i].strExcept[1]);
    mexcept2= new Money(Convert.ToInt32(tdTest[i].strExcept[2]), tdTest[i].strExcept[3]);
    mbexcept = new MoneyBag(mexcept1, mexcept2);
    }
     數(shù)據(jù)表中的數(shù)據(jù)全部以字符串類型讀入構造體數(shù)組中,使用時,根據(jù)具體情況將字符串類型轉換為對應數(shù)據(jù)類型參與測試。公共處理以外的個性數(shù)據(jù)讀取可在各測試方法中實現(xiàn)。
2.4 各測試方法的實現(xiàn)
    將Nunit自帶的樣例測試腳本按照本文提出的方法進行改編,下面是實現(xiàn)單一貨幣錢包加法的改編腳本(其他方法基本類似):
    [Test]
    public void BagSimpleAdd()
    {
    int intI = GetPrivateProfileString("ROWS", "BagSimpleAdd", "", tmpRow, 500, striniPath + "\\moneytest.ini");
    int i = Convert.ToInt32(Convert.ToString(tmpRow));
    SetValue(i);
    Assert.AreEqual(mbexcept, fMB1.Add(f14CHF));
    }

 


    利用本文提出的方法對Nunit自帶測試類Monytest.cs中的所有方法進行改編,執(zhí)行結果與自帶測試類一致。與原來的方法相比較,本文提出的方法實現(xiàn)了測試腳本與測試數(shù)據(jù)的分離,對測試用例的維護基本可通過對Excel數(shù)據(jù)文件和ini文件的維護來實現(xiàn),從而降低了測試腳本維護過程中產(chǎn)生的維護成本。在后續(xù)的研究中,將根據(jù)本文提出的方法,進一步探索測試腳本自動生成的實現(xiàn),以進一步提高測試腳本的開發(fā)效率。
參考文獻
[1] 劉德寶.軟件測試工程師培訓教材[M].北京:科學出版社,2009.
[2] 林勤花.使用NUnit在.net編程中進行單元測試[J].科技信息,2008(24):410-411.
[3] 陸復名. NUnit.NET項目測試點評[J].程序員,2004(11):128-129.
[4] 陳技能.QTP自動化測試實踐[M]. 北京:電子工業(yè)出版社,2009.
[5] 劉曉丹,武君勝,劉博.基于數(shù)據(jù)驅動的自動化測試平臺設計[J].科學技術與工程,2008,8(3):779-782.

此內容為AET網(wǎng)站原創(chuàng),未經(jīng)授權禁止轉載。
亚洲一区二区欧美_亚洲丝袜一区_99re亚洲国产精品_日韩亚洲一区二区
99视频精品免费观看| av成人免费在线观看| 欧美激情日韩| 裸体女人亚洲精品一区| 亚洲午夜一级| 9色porny自拍视频一区二区| 亚洲经典三级| 亚洲国产欧美日韩精品| 欧美在线精品一区| 欧美一区二区三区免费观看| 欧美一级视频一区二区| 性久久久久久久久| 亚洲欧美日韩在线综合| 亚洲欧美视频在线观看| 亚洲欧美中文在线视频| 先锋影音久久久| 欧美专区一区二区三区| 久久成人免费电影| 亚洲国产精品电影在线观看| 最新高清无码专区| 日韩午夜剧场| 国产精品99久久久久久久vr| 亚洲午夜在线观看| 亚洲综合色在线| 香蕉成人久久| 久久久久久一区二区| 久久字幕精品一区| 每日更新成人在线视频| 欧美大香线蕉线伊人久久国产精品| 欧美成年人视频网站| 欧美精品乱码久久久久久按摩| 欧美紧缚bdsm在线视频| 欧美剧在线观看| 国产精品多人| 国产一区二区三区四区hd| 伊人久久大香线蕉综合热线| 91久久精品国产91性色tv| 国产香蕉久久精品综合网| 国产综合色产| 亚洲国产综合91精品麻豆| 亚洲九九爱视频| 亚洲一区二区三区777| 午夜精品一区二区三区在线播放| 久久成人免费日本黄色| 亚洲精品日韩综合观看成人91| 中文av字幕一区| 香蕉乱码成人久久天堂爱免费| 久久精品视频在线免费观看| 免费欧美高清视频| 欧美日韩国产高清| 国产精品福利在线观看网址| 国产日韩一区在线| 在线日韩av片| 夜夜嗨av一区二区三区网站四季av | 亚洲一区日本| 久久国产天堂福利天堂| 欧美顶级大胆免费视频| 国产精品久久一级| 影音先锋久久久| 亚洲视频1区| 亚洲第一中文字幕在线观看| 一区二区三区色| 久久久噜噜噜久久人人看| 欧美日韩系列| 黑人巨大精品欧美一区二区| 亚洲乱码日产精品bd| 久久99伊人| 国产精品99久久久久久宅男| 久久久久国产成人精品亚洲午夜| 欧美精品一区二区三区很污很色的| 国产精品嫩草影院av蜜臀| 激情另类综合| 亚洲综合社区| 一本一本久久a久久精品牛牛影视| 久久国产婷婷国产香蕉| 欧美视频精品一区| 在线观看日韩av先锋影音电影院 | 香蕉久久夜色精品国产| 亚洲最新中文字幕| 久久人人爽人人| 国产精品户外野外| 亚洲国产高清自拍| 欧美一区二区视频在线| 亚洲视频在线视频| 欧美成人一区二区三区片免费| 国产欧美一区二区三区久久人妖 | 亚洲视频久久| 免费美女久久99| 国产视频久久网| 中文精品一区二区三区 | 欧美精品成人| 伊人久久综合| 欧美亚洲视频在线观看| 亚洲综合激情| 欧美久久久久中文字幕| 在线成人国产| 久久狠狠久久综合桃花| 午夜精品婷婷| 国产精品久久久久久久久久免费看 | 欧美色图首页| 亚洲激情影视| 亚洲国产清纯| 久久久青草青青国产亚洲免观| 国产精品久久7| 洋洋av久久久久久久一区| 亚洲人成亚洲人成在线观看图片| 久久人人爽国产| 国产性做久久久久久| 亚洲自拍偷拍视频| 亚洲无线视频| 欧美日韩免费看| 亚洲精品久久在线| 亚洲娇小video精品| 另类综合日韩欧美亚洲| 国产一区二区三区高清| 午夜视频一区在线观看| 午夜免费电影一区在线观看| 国产精品家教| 亚洲免费一级电影| 亚洲免费小视频| 欧美性猛交视频| 中文日韩欧美| 亚洲欧美一区二区激情| 国产精品久久久91| 亚洲视频观看| 亚洲欧美日韩精品久久久久| 国产精品日日摸夜夜添夜夜av| 亚洲天堂免费观看| 亚洲欧美日韩一区二区| 国产精品毛片高清在线完整版| 亚洲一区二区3| 欧美一区二区三区四区在线观看地址 | 性8sex亚洲区入口| 国产精品综合色区在线观看| 亚洲欧美中文日韩在线| 久久精品视频在线观看| 国内伊人久久久久久网站视频| 久久国产精品久久久久久久久久| 久久婷婷国产综合精品青草 | 亚洲国产一区在线观看| 亚洲免费成人av| 欧美日韩国产精品| 亚洲午夜精品久久| 欧美一区二区三区男人的天堂| 国产精品亚洲综合一区在线观看 | 亚洲狠狠丁香婷婷综合久久久| 亚洲欧洲精品成人久久奇米网| 欧美黑人一区二区三区| 夜夜嗨av一区二区三区四季av| 亚洲欧美日韩一区二区| 国产亚洲精品7777| 亚洲区免费影片| 欧美视频在线免费| 亚洲一区二区免费视频| 久久精品国产第一区二区三区最新章节| 国产一区二区三区精品欧美日韩一区二区三区 | 国产精品久久久久9999高清 | 欧美一区综合| 免费看黄裸体一级大秀欧美| 亚洲三级网站| 亚洲欧美日韩一区在线观看| 国产一区二区三区精品欧美日韩一区二区三区 | 一本色道精品久久一区二区三区| 国产精品久久777777毛茸茸| 午夜精彩视频在线观看不卡| 久久综合狠狠综合久久综合88 | 日韩一二三区视频| 国产精品美女一区二区| 羞羞漫画18久久大片| 欧美freesex交免费视频| 99在线精品视频在线观看| 午夜在线一区二区| 一区二区在线免费观看| 亚洲深爱激情| 国产一区二区视频在线观看 | 亚洲精品视频二区| 午夜欧美精品| 亚洲缚视频在线观看| 亚洲女同同性videoxma| 黄网站免费久久| 亚洲午夜激情免费视频| 国产在线国偷精品产拍免费yy| 一本色道婷婷久久欧美| 国产综合精品| 亚洲午夜精品视频| 黄色国产精品一区二区三区| 亚洲视频在线观看视频| 狠狠色综合网| 欧美在线综合| 国产精品久久久久久久久久三级| 欧美中在线观看| 欧美午夜精品一区二区三区| 亚洲国产高清在线观看视频| 国产精品videossex久久发布| 亚洲人体一区| 国产一区二区三区在线观看精品 | 伊甸园精品99久久久久久| 亚洲男人的天堂在线观看| 亚洲国产精品女人久久久| 久久成人资源|