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

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

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

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

    過程①中讀取[FILE]和[DATA]節中的值,用于定位測試數據文件和定義結構體數組維數;過程②按行列依次循環,將數據表中的數據依次全部讀入結構體數組;過程③初始化各測試方法的公用數據,下面是按照本文提出的方法,以Nunit自帶的樣例測試腳本MoneyTest.cs為例對公共輸入數據進行設定的相關代碼:
    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的結構體數組中存放公共測試數據,則在上面的代碼前可直接將i賦值為0,也可讀取ini文件的Common值來設定i值。
2.3 自定義方法的實現
    每一個方法執行之前都需要讀取結構體數組中對應行的數據,雖然讀取數據的代碼可以寫在各測試方法中,但這無疑會產生重復代碼。通過分析各測試方法讀取數據的相似部分,可將這部分代碼寫成一個公用方法,[SetUp]中定義的方法能保證各方法執行之前自動執行一次,但是該方法不能帶參數。因此,這里自定義一個帶參數的方法供各測試方法調用。同樣以Moneybag類的測試為例,該測試類中,各方法的輸入基本采用公共數據,各方法的預期結果各不相同,因此各方法均有一個讀取預期結果的公共處理,將這部分處理用自定義方法實現,參數i為各方法對應的測試數據的數組下標。代碼如下:
    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);
    }
     數據表中的數據全部以字符串類型讀入構造體數組中,使用時,根據具體情況將字符串類型轉換為對應數據類型參與測試。公共處理以外的個性數據讀取可在各測試方法中實現。
2.4 各測試方法的實現
    將Nunit自帶的樣例測試腳本按照本文提出的方法進行改編,下面是實現單一貨幣錢包加法的改編腳本(其他方法基本類似):
    [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中的所有方法進行改編,執行結果與自帶測試類一致。與原來的方法相比較,本文提出的方法實現了測試腳本與測試數據的分離,對測試用例的維護基本可通過對Excel數據文件和ini文件的維護來實現,從而降低了測試腳本維護過程中產生的維護成本。在后續的研究中,將根據本文提出的方法,進一步探索測試腳本自動生成的實現,以進一步提高測試腳本的開發效率。
參考文獻
[1] 劉德寶.軟件測試工程師培訓教材[M].北京:科學出版社,2009.
[2] 林勤花.使用NUnit在.net編程中進行單元測試[J].科技信息,2008(24):410-411.
[3] 陸復名. NUnit.NET項目測試點評[J].程序員,2004(11):128-129.
[4] 陳技能.QTP自動化測試實踐[M]. 北京:電子工業出版社,2009.
[5] 劉曉丹,武君勝,劉博.基于數據驅動的自動化測試平臺設計[J].科學技術與工程,2008,8(3):779-782.

此內容為AET網站原創,未經授權禁止轉載。
热re99久久精品国产66热_欧美小视频在线观看_日韩成人激情影院_庆余年2免费日韩剧观看大牛_91久久久久久国产精品_国产原创欧美精品_美女999久久久精品视频_欧美大成色www永久网站婷_国产色婷婷国产综合在线理论片a_国产精品电影在线观看_日韩精品视频在线观看网址_97在线观看免费_性欧美亚洲xxxx乳在线观看_久久精品美女视频网站_777国产偷窥盗摄精品视频_在线日韩第一页
  • <strike id="ygamy"></strike>
  • 
    
      • <del id="ygamy"></del>
        <tfoot id="ygamy"></tfoot>
          <strike id="ygamy"></strike>
          久久免费一区| 在线亚洲欧美视频| 国产日韩欧美高清| 亚洲一区二区四区| 欧美一区二区精美| 91久久精品www人人做人人爽| 久久爱91午夜羞羞| 国产女主播在线一区二区| 欧美日韩国产丝袜另类| 亚洲免费观看高清完整版在线观看熊| 一区二区三区欧美视频| 国产视频久久久久| 亚洲国产色一区| 国产乱人伦精品一区二区| 亚洲国产精品第一区二区| 欧美激情偷拍| 国产偷自视频区视频一区二区| 在线不卡中文字幕| 国产精品免费在线| 欧美日韩精品二区第二页| 亚洲欧洲一区二区三区久久| 亚洲免费在线| 亚洲国产日日夜夜| 国产伦精品一区二区三区高清版| 欧美色图麻豆| 欧美日韩国产麻豆| 好吊色欧美一区二区三区四区| 一区二区视频免费在线观看| 亚洲美女尤物影院| 国内久久精品视频| 午夜欧美精品久久久久久久| 亚洲黄色性网站| 欧美一级在线亚洲天堂| 欧美三日本三级少妇三99| 久久久久久亚洲精品不卡4k岛国| 一区二区高清视频| 国产精品久久久久7777婷婷| 国产精品亚洲一区二区三区在线| 午夜伦欧美伦电影理论片| 久久gogo国模啪啪人体图| 国产一区二区三区四区老人| 欧美激情一区二区三区蜜桃视频| 欧美日韩在线一区二区三区| 亚洲乱码视频| 久久九九精品99国产精品| 欧美视频中文字幕在线| 亚洲欧美福利一区二区| 欧美视频1区| 欧美国产日韩精品| 久久精彩免费视频| 欧美三区免费完整视频在线观看| 欧美一区激情视频在线观看| 亚洲一区二三| 久久综合中文| 久久久精品国产一区二区三区| 日韩午夜激情电影| 欧美激情成人在线| 国产日韩欧美成人| 国产精品视频久久久| 一本久久综合亚洲鲁鲁五月天| 国产精品私房写真福利视频| 亚洲夜晚福利在线观看| 欧美日韩视频免费播放| 欧美国产一区二区三区激情无套| 国内久久精品| 亚洲黄一区二区| 久久影音先锋| 亚洲经典在线| 亚洲日本va午夜在线影院| 欧美日韩四区| 国产精品午夜久久| 午夜欧美大片免费观看| 午夜国产不卡在线观看视频| 久久国产日本精品| 亚洲欧美成人在线| 亚洲成人在线视频播放| 亚洲最新在线视频| 亚洲免费一级电影| 国产精品一区二区三区久久久| 欧美成人精品不卡视频在线观看| 亚洲黄色在线视频| 欧美国产日韩a欧美在线观看| 亚洲日本免费| 欧美日韩国产精品| 久久成人综合视频| 国产精品无码永久免费888| 久久免费精品日本久久中文字幕| 国产综合一区二区| 亚洲精品国产精品国自产在线| 黄色综合网站| 好吊色欧美一区二区三区四区| 亚洲国产欧美在线人成| 欧美成人激情视频| 亚洲精品一区二区三区婷婷月| 欧美福利电影在线观看| 亚洲人久久久| 国产毛片久久| 老司机免费视频一区二区三区| 欧美视频网站| 国产精品乱码一区二区三区| 国产精品久久久久久久免费软件| 91久久极品少妇xxxxⅹ软件| 欧美国产精品va在线观看| 亚洲夜晚福利在线观看| 亚洲欧美色一区| 欧美久久久久久久久久| 欧美色大人视频| 欧美伦理91i| 国产精品成人久久久久| 好男人免费精品视频| 亚洲一区二区欧美日韩| 欧美凹凸一区二区三区视频| 亚洲欧美一区二区激情| 国产一区在线观看视频| 国产精品免费aⅴ片在线观看| 亚洲深爱激情| 在线精品观看| 久久精品欧美日韩精品| 美女诱惑黄网站一区| 亚洲字幕在线观看| 宅男噜噜噜66一区二区| 国产精品久久看| 国产日韩精品在线| 国产伦一区二区三区色一情| 亚洲日韩欧美视频| 蜜臀av性久久久久蜜臀aⅴ四虎| 欧美精品亚洲精品| 性色av一区二区三区在线观看| 欧美一区二区免费观在线| 欧美日韩一区二| 黄色亚洲精品| 欧美系列一区| 亚洲国产精品悠悠久久琪琪| 欧美日本高清一区| 欧美影院一区| 国产一区二区三区久久| 亚洲一区二区三区成人在线视频精品| 1769国内精品视频在线播放| 亚洲高清免费| 亚洲欧美日韩精品一区二区| 亚洲视频在线观看三级| 久久精品国产一区二区三| 欧美成人一区二区在线| 欧美国产丝袜视频| 久久精品在线观看| 亚洲国产成人av好男人在线观看| 一区二区三区欧美视频| 在线视频欧美一区| 久久久久成人网| 欧美一区二区三区在线观看| 国内精品一区二区三区| 亚洲精品欧洲| 久久久999精品免费| 久久精品亚洲精品国产欧美kt∨| 国一区二区在线观看| 娇妻被交换粗又大又硬视频欧美| 一区二区三区日韩精品视频| 国产一区二区三区四区三区四| 欧美一区二粉嫩精品国产一线天| 亚洲国产日韩欧美在线动漫| 亚洲美女视频在线免费观看| 欧美精品亚洲二区| 日韩午夜剧场| 欧美交受高潮1| 久久色在线播放| 亚洲视频香蕉人妖| 国产亚洲福利| 亚洲欧美激情四射在线日| 亚洲大片av| 欧美一区午夜视频在线观看| 在线中文字幕一区| 在线观看成人网| 午夜一区二区三区不卡视频| 国产精品国产三级国产普通话99| 欧美性猛片xxxx免费看久爱| 在线不卡欧美| 欧美精品亚洲二区| 1000精品久久久久久久久| 亚洲精品在线观看视频| 亚洲毛片播放| 久久一区二区精品| 中文一区二区| 午夜综合激情| 一本色道久久综合| 亚洲资源av| 一卡二卡3卡四卡高清精品视频| 91久久午夜| 亚洲欧美国产精品桃花| 狠狠狠色丁香婷婷综合久久五月| 亚洲精品国产拍免费91在线| 欧美成人午夜激情| 久久成人精品| 久久天堂av综合合色| 午夜精品影院| 久久狠狠久久综合桃花| 亚洲综合清纯丝袜自拍| 国产日韩欧美在线播放| 久久久久99| 在线日韩中文字幕| 免费成人高清| 欧美亚洲第一区| 国产精品网红福利| 国产三级欧美三级| 欧美伊人久久久久久午夜久久久久| 国产一区导航| 亚洲第一精品影视| 在线观看亚洲精品视频| 欧美承认网站| 久久色中文字幕| 久久综合成人精品亚洲另类欧美| 欧美体内she精视频在线观看| 久久久久成人精品免费播放动漫| 欧美日韩一二三区| 亚洲欧洲日产国产综合网| 91久久精品视频| 久久久久久999| 久久在线91| 国产精品vvv| 欧美日韩国产经典色站一区二区三区| 久久中文字幕一区二区三区| 欧美成年人视频| 久久一区二区三区国产精品| 久久一区二区三区国产精品| av成人福利| 久久精品国产亚洲一区二区三区| 欧美视频一区二区| 国产精品一级二级三级| 国产精品自拍一区| 亚洲三级视频在线观看| 亚洲成人在线网站| 欧美日韩另类丝袜其他| 国产嫩草一区二区三区在线观看| 国产日韩一级二级三级| 国产精品嫩草影院av蜜臀| 久久久久中文| 一区在线电影| 狠狠噜噜久久| 亚洲高清网站| 欧美系列电影免费观看| 亚洲欧洲一级| 欧美日韩国产天堂| 一区二区高清| 亚洲精品小视频在线观看| 久久久xxx| 亚洲视频电影图片偷拍一区| 欧美片在线播放| 欧美日韩国产综合视频在线观看中文| 欧美性猛交视频| 久久久精品一品道一区| 一区二区三区在线观看欧美| 一本色道久久综合亚洲精品按摩| 六月天综合网| 久热国产精品视频| 国产精品不卡在线| 亚洲午夜精品网| 日韩午夜视频在线观看| 欧美韩日一区| 久久精品视频在线观看| 欧美性色视频在线| 91久久精品一区| 麻豆精品视频在线观看视频| 国产日韩欧美在线播放| 国产精品一二三视频| 欧美性大战久久久久久久| 久久亚洲综合色| 久久久午夜视频| 在线视频欧美日韩精品| 一本色道久久加勒比精品| 欧美日韩成人一区二区| 国产一区二区中文字幕免费看| 欧美三级韩国三级日本三斤| 亚洲人精品午夜在线观看| 国产精品成人一区二区网站软件| 国产精品v亚洲精品v日韩精品| 亚洲香蕉成视频在线观看| 欧美高清视频一区二区三区在线观看| 亚洲成色999久久网站| 久久亚洲美女| 亚洲欧洲中文日韩久久av乱码| 国产精品成av人在线视午夜片| 一区二区三区成人| 日韩视频在线免费观看| 一色屋精品视频免费看| 久久国产一区二区三区| 久久久久**毛片大全| 亚洲国产一成人久久精品| 国产精品夜夜夜| 欧美日韩在线视频首页| 久久婷婷国产综合国色天香| 韩日精品中文字幕| 久久噜噜噜精品国产亚洲综合| 国产精品播放| 国产精品红桃| 久久婷婷丁香| 国内精品久久久久国产盗摄免费观看完整版| 狠色狠色综合久久| 在线视频欧美日韩| 国产精品丝袜白浆摸在线| 在线日韩中文| 亚洲美女av黄| 亚洲图片欧洲图片av| 艳妇臀荡乳欲伦亚洲一区| 欧美电影免费观看网站| 久久国产加勒比精品无码| 久久国产精品72免费观看| 久热国产精品视频| 亚洲国产91精品在线观看| 欧美激情按摩| 香蕉视频成人在线观看| 国产精品福利网站| 欧美中文在线免费| 一区在线视频观看| 亚洲美女黄色片| 欧美福利精品| 在线成人激情视频| 牛牛国产精品| 久久免费少妇高潮久久精品99| 欧美天堂在线观看| 欧美日本国产视频| 欧美成ee人免费视频| 欧美一区在线直播| 亚洲国产小视频在线观看| 蜜桃av噜噜一区二区三区| 亚洲免费电影在线观看| 国产精品中文字幕在线观看| 一区二区国产日产| 国产精品国码视频| 久久久久国产免费免费|