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

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

3.屬性的應用

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

3.1 NUnit中的屬性應用

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

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

//一個NUnit測試程序集中代碼

[SetUp]

public void Init()

//…

[TearDown]

public void Destroy()

//…

[Test]

public void TestXXX()

//…

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

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

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

//From TemplateTestCase in NUnit.Core namespace

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

public override void Run(TestCaseResult testResult )

{

   //…

try{

        //…

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

     //…

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

//…

}

catch(…)

//…

finally {

  //…

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

//…

}

//…

}

        而InvokeXXX()函數(shù)則利用反射機制運行相關函數(shù),可以看看以下幾個代碼段:

//From TemplateTestCase in NUnit.Core namespace

private void InvokeSetUp()

{

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

       if(method != null)

       {

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

       }

}

        FindSetUpMethod(…)通過調(diào)用一個叫FindMethodByAttribute(…)的函數(shù),利用反射機制來獲得可調(diào)用該函數(shù)的MethodInfo,并后通過InvokeMethod(MethodInfo,…)來運行。

//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實例反射的方法或構(gòu)造函數(shù)

           }

           catch(…)

           //…

       }

}

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

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

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