您的位置:軟件測(cè)試 > 開源軟件測(cè)試 > 開源單元測(cè)試工具 > Nunit
從NUnit中理解.NET自定義屬性的應(yīng)用
作者:網(wǎng)絡(luò)轉(zhuǎn)載 發(fā)布時(shí)間:[ 2013/3/28 13:26:34 ] 推薦標(biāo)簽:

        自定義屬性可以用于對(duì)程序集中的元素進(jìn)行標(biāo)記和描述,并被編譯到.NET程序集中,成為其元數(shù)據(jù)的一部分。而從屬性和屬性值的讀取是對(duì).NET程序集元數(shù)據(jù)的讀取,這會(huì)用到反射機(jī)制。具體如何編寫自定義屬性和如何讀取屬性的例子在MSDN中有很多,不再冗述了。

3.屬性的應(yīng)用

        屬性的以上的特性往往在設(shè)計(jì)一些框架時(shí)很有用:利用反射機(jī)制,作為屬性的元數(shù)據(jù)可以反過(guò)來(lái)在運(yùn)行期影響代碼的運(yùn)行配置項(xiàng),或者為特殊的操作方法作以屬性作標(biāo)記,以便在運(yùn)行時(shí)做特殊處理。屬性的另一個(gè)很有誘惑力的應(yīng)用是,可以用于構(gòu)建管理項(xiàng)目程序集的工具:屬性表現(xiàn)為某種注釋,而注釋內(nèi)容可以在編譯后從程序集中讀取出來(lái),從而可以通過(guò)屬性內(nèi)容的注釋和讀取來(lái)實(shí)現(xiàn)對(duì)程序集中各類型、方法的管理了。

3.1 NUnit中的屬性應(yīng)用

        先看看屬性在框架設(shè)計(jì)中的應(yīng)用吧!典型的例子是NUnit。在NUnit的框架設(shè)計(jì)中將自定義屬性的特性、以及.NET的反射機(jī)制發(fā)揮得淋漓盡致。以一個(gè)簡(jiǎn)化了的測(cè)試案例(TestCase)為例:在測(cè)試時(shí),NUnit需要讓其中3種不同的函數(shù)依次運(yùn)行如下:

        首先前運(yùn)行測(cè)試前的環(huán)境準(zhǔn)備函數(shù);然后是0~n個(gè)測(cè)試函數(shù);后是測(cè)試環(huán)境清理函數(shù)。熟悉NUnit的開發(fā)者都知道,在NUnit的TestCase中分別使用[SetUp]、[Test]、[TearDown]屬性來(lái)進(jìn)行標(biāo)記。如下例:

//一個(gè)NUnit測(cè)試程序集中代碼

[SetUp]

public void Init()

//…

[TearDown]

public void Destroy()

//…

[Test]

public void TestXXX()

//…

        NUnit框架在運(yùn)行時(shí)要從待測(cè)試程序集中讀取出上述函數(shù),并且要保證上述3種不同的函數(shù)以正確的先后順序被依次調(diào)用。NUnit是這樣實(shí)現(xiàn)的:

        首先是開發(fā)了一套屬性,用來(lái)標(biāo)記測(cè)試案例(TestCase)中各種函數(shù),如:[SetUp]、[Test]、[TearDown]。(NUnit的屬性標(biāo)記并不止用來(lái)標(biāo)記程序集中的函數(shù),但限于篇幅,這里只在先前作的簡(jiǎn)化環(huán)境中討論)

        NUnit在運(yùn)行時(shí)利用反射機(jī)制運(yùn)行已經(jīng)被編譯成程序集的測(cè)試案例(TestCase)中的函數(shù)。NUnit框架中有一系列的函數(shù)來(lái)完成這項(xiàng)工作,這些函數(shù)只負(fù)責(zé)運(yùn)行測(cè)試案例程序集中特定屬性標(biāo)記所標(biāo)記的函數(shù)。如:InvokeSetUp()負(fù)責(zé)運(yùn)行標(biāo)記有[SetUp]的函數(shù);InvokeTestCase()負(fù)責(zé)運(yùn)行標(biāo)記有[Test]的函數(shù),即測(cè)試案例;InvokeTearDown()負(fù)責(zé)運(yùn)行標(biāo)記有[TearDown]的函數(shù)。然后NUnit利用這幾個(gè)InvokeXXX()函數(shù)的調(diào)用先后來(lái)保證這3種函數(shù)運(yùn)行的先后順序。

//From TemplateTestCase in NUnit.Core namespace

//用于執(zhí)行測(cè)試的Run函數(shù)

public override void Run(TestCaseResult testResult )

{

   //…

try{

        //…

     InvokeSetUp();//首先運(yùn)行標(biāo)有[SetUp]標(biāo)記的函數(shù)

     //…

InvokeTestCase();//然后是[Test]

//…

}

catch(…)

//…

finally {

  //…

        InvokeTearDown();//后是[TearDown]標(biāo)記的函數(shù)

//…

}

//…

}

        而InvokeXXX()函數(shù)則利用反射機(jī)制運(yùn)行相關(guān)函數(shù),可以看看以下幾個(gè)代碼段:

//From TemplateTestCase in NUnit.Core namespace

private void InvokeSetUp()

{

MethodInfo method = FindSetUpMethod(fixture);//取得[SetUp]標(biāo)記的函數(shù)反射實(shí)例

       if(method != null)

       {

              InvokeMethod(method, fixture);//運(yùn)行該函數(shù)

       }

}

        FindSetUpMethod(…)通過(guò)調(diào)用一個(gè)叫FindMethodByAttribute(…)的函數(shù),利用反射機(jī)制來(lái)獲得可調(diào)用該函數(shù)的MethodInfo,并后通過(guò)InvokeMethod(MethodInfo,…)來(lái)運(yùn)行。

//From Test class in NUnit.Core namespace

protected void InvokeMethod(MethodInfo method, object fixture)

{

if(method != null)

       {

       try

           {

                  method.Invoke(fixture, null);//調(diào)用由method實(shí)例反射的方法或構(gòu)造函數(shù)

           }

           catch(…)

           //…

       }

}

        仔細(xì)閱讀源碼可以看到因?yàn)镹Unit使用反射機(jī)制來(lái)運(yùn)行測(cè)試程序集中的測(cè)試案例,所以對(duì)[SetUp]、[Test]、[TearDown]函數(shù)的返回值、參數(shù)都有具體的要求,形成了一種規(guī)則耦合。這是為了方便反射實(shí)現(xiàn)、簡(jiǎn)化框架而作出的必要設(shè)計(jì)。

        由NUnit可以看到.NET元數(shù)據(jù)擴(kuò)展中的自定義屬性在框架設(shè)計(jì)中的應(yīng)用,相信會(huì)有更多的框架類項(xiàng)目利用.NET自定義屬性的特性。下面是本文涉及的幾個(gè)類在NUnit中的關(guān)系(已經(jīng)作了簡(jiǎn)化)。

上一頁(yè)123下一頁(yè)
軟件測(cè)試工具 | 聯(lián)系我們 | 投訴建議 | 誠(chéng)聘英才 | 申請(qǐng)使用列表 | 網(wǎng)站地圖
滬ICP備07036474 2003-2017 版權(quán)所有 上海澤眾軟件科技有限公司 Shanghai ZeZhong Software Co.,Ltd