《電子技術應用》
您所在的位置:首頁 > 測試測量 > 設計應用 > 數(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亚洲国产精品_日韩亚洲一区二区
一本色道久久综合一区| 亚洲第一网站| 18成人免费观看视频| 国产麻豆91精品| 国产精品日韩电影| 国产精品成人播放| 欧美日韩视频一区二区| 欧美精品综合| 欧美精品黄色| 欧美精品成人| 欧美精品免费视频| 欧美精品自拍| 欧美日韩另类字幕中文| 欧美精品一区二区三区很污很色的| 美女脱光内衣内裤视频久久网站| 久久久久久一区| 久久久999国产| 久久久精品午夜少妇| 久久精品一区| 久久日韩粉嫩一区二区三区| 久久久久se| 久久野战av| 你懂的国产精品| 欧美搞黄网站| 欧美屁股在线| 欧美日韩小视频| 国产精品国码视频| 国产精品天天摸av网| 国产日韩成人精品| 国模精品一区二区三区| 一区二区三区在线免费视频| 亚洲福利国产| 亚洲精选在线观看| 亚洲一区二区在线看| 亚洲免费在线视频| 午夜视频一区| 亚洲高清资源| 亚洲精品日韩一| 一区二区三区四区国产精品| 亚洲欧美制服另类日韩| 久久精品女人天堂| 欧美成人蜜桃| 国产精品电影网站| 国产一区二区高清视频| 亚洲电影成人| 亚洲私人影院| 久久国产精品一区二区三区四区| 亚洲欧洲美洲综合色网| 亚洲深爱激情| 久久久国产精品一区二区三区| 免费在线视频一区| 欧美体内she精视频在线观看| 国产欧美一区二区三区另类精品| 伊人成人网在线看| 亚洲精品综合精品自拍| 亚洲男女毛片无遮挡| 亚洲激情网站免费观看| 亚洲午夜精品久久久久久app| 欧美一区二区视频观看视频| 欧美/亚洲一区| 国产精品av久久久久久麻豆网| 国产一区在线观看视频| 亚洲欧洲另类国产综合| 亚洲欧美激情一区| 亚洲免费成人av| 欧美一级日韩一级| 欧美二区在线播放| 国产精品视频久久一区| 在线观看日韩欧美| 亚洲性感激情| 亚洲人成在线观看网站高清| 午夜精品久久久久久久白皮肤 | 日韩亚洲精品在线| 欧美在线看片| 欧美人与禽性xxxxx杂性| 国产一区二区三区无遮挡| 亚洲精品在线看| 久久aⅴ国产紧身牛仔裤| 亚洲深夜影院| 欧美r片在线| 国产亚洲观看| 国产精品99久久久久久久久| 亚洲欧洲在线看| 欧美在线日韩| 国产精品地址| 亚洲乱码精品一二三四区日韩在线 | 美女尤物久久精品| 国产欧美亚洲日本| 一本一本久久a久久精品综合麻豆| 亚洲激情在线播放| 久久国产视频网站| 国产精品va在线播放我和闺蜜| 亚洲电影免费观看高清完整版在线| 亚洲欧美三级伦理| 亚洲视频在线观看网站| 欧美黄色网络| 影音先锋日韩资源| 久久精品国产久精国产爱| 香蕉成人啪国产精品视频综合网| 欧美乱在线观看| 亚洲成人资源网| 欧美在线首页| 久久都是精品| 国产伦精品一区二区三区在线观看 | 午夜在线观看欧美| 欧美一级视频| 国产精品色午夜在线观看| 一本色道久久综合亚洲精品不 | 欧美激情va永久在线播放| 精品成人久久| 亚洲第一主播视频| 久久夜色精品国产欧美乱极品| 国产欧美日韩伦理| 亚洲一区三区视频在线观看| 亚洲一区二区三区国产| 欧美人妖另类| 亚洲人成亚洲人成在线观看图片| 亚洲日本欧美日韩高观看| 国产精品久久久久免费a∨大胸 | 亚洲综合清纯丝袜自拍| 欧美精品在欧美一区二区少妇| 影音先锋亚洲一区| 久久精品夜色噜噜亚洲a∨ | 免费欧美视频| 亚洲国产精品日韩| 亚洲免费观看| 欧美激情第10页| 亚洲精品国产精品乱码不99| 99国产一区| 欧美日韩国产小视频在线观看| 亚洲精品视频一区二区三区| 夜夜躁日日躁狠狠久久88av| 欧美日韩免费一区二区三区| 日韩午夜激情av| 亚洲一区二区三区国产| 国产精品久久久久久久9999| 亚洲夜间福利| 久久电影一区| 黄色另类av| 91久久在线视频| 欧美日韩精品免费观看视频| 一区二区三区回区在观看免费视频| 一区二区三区四区蜜桃| 国产精品久久一级| 香港久久久电影| 久久精品免费播放| 一区二区亚洲精品国产| 亚洲美女视频在线观看| 欧美日韩黄色大片| 一本一本久久a久久精品综合麻豆| 午夜精品一区二区三区四区 | 国产一区二区三区四区五区美女| 亚洲国产精品99久久久久久久久| 欧美二区在线播放| 99精品国产99久久久久久福利| 亚洲综合色网站| 国产一区二区三区的电影| 亚洲激情成人在线| 欧美色视频一区| 欧美一区二区三区免费在线看 | 国产香蕉久久精品综合网| 亚洲国产日韩一区二区| 欧美日本一区二区高清播放视频| 亚洲性视频网站| 久久影音先锋| 日韩一区二区精品葵司在线| 欧美伊人久久久久久午夜久久久久| 黄色日韩在线| 亚洲一级二级在线| 久久久免费av| 99re成人精品视频| 久久精品国产免费看久久精品| 91久久精品美女| 欧美一区二区高清在线观看| 亚洲第一精品电影| 亚洲一区欧美二区| 精品91在线| 午夜精品免费| 亚洲日本视频| 久久久久久久久久码影片| 亚洲久久在线| 久久久久国产精品厨房| 99热免费精品在线观看| 久久青草欧美一区二区三区| 99精品国产福利在线观看免费| 久久深夜福利| 亚洲一二三区在线| 欧美精品 国产精品| 午夜视频在线观看一区二区三区| 欧美精品电影在线| 久久高清国产| 国产精品对白刺激久久久| 亚洲国产视频直播| 国产精品一卡| 亚洲手机在线| 伊人成人网在线看| 欧美一区二区在线视频| 99riav国产精品| 欧美.www| 久久精品夜色噜噜亚洲aⅴ|