NUnit使用詳解(一)


轉載:http://hi.baidu.com/grayworm/item/38e246165aa7b9433a176e90

NUnit是一個單元測試框架,專門針對於.NET來寫的,它是是xUnit的一員。NUnit完全由C#語言來編寫,並且編寫時充分利用了許多.NET的特性,比如反射,客戶屬性等等.
最重要的一點是它適合於所有.NET語言.

單元測試:
作為程序員在開發過程中,不可避免地要對軟件的類及其方法進行測試。
在Web頁面的測試過程中,好多朋友喜歡把測試結果使用Response.Write()顯示在頁面上。而在類庫組件的開發時,由於沒有可視化界面,有時不得不為該類庫添模一個測試的項目(Console,WinForm,ASP.NET等),在該項目中調用類庫組件的功能,以查看測試結果。
上面這種測試不是我們推薦的方法,因為我們在測試的時候應遵循以下原則:
    
盡量不要破壞原有的代碼結構,即不要在原代碼中添加一些冗余的測試代碼。
    測試模塊應盡可能完整地展現測試結果。
    測試模塊不應用完即扔掉,要保存以備后續的維護測試。
    
一、NUnit運行界面

1

《圖1》
在右邊有一個進度條,如果所有測試案例運行成功,就為綠色,反之如果有一個不成功,則為紅色,但也有黃色的.
    綠色 描述目前所執行的測試都通過 
    黃色 意味某些測試忽略,但是這里沒有失敗 
    紅色 表示有失敗

左邊的樹狀目錄是我們們編寫的每一個測試單元。

底部的狀態條
    狀態:當所有測試完成時,狀態變為Completed.運行測試中,狀態是Running: <test-name>
    Test Cases:說明加載的程序集中測試案例的總個數。這也是測試樹里葉子節點的個數。 
    Tests Run: 已經完成的測試個數。 
    Failures: 到目前為止,所有測試中失敗的個數. 
    Time: 顯示運行測試時間(以秒計)

二、在VS2008中配置NUnit進行測試
    
1.新建一個類庫項目。
    2.在解決方案中的項目圖標上右擊,選擇“屬性”。
    3.點擊左邊的“調試”標簽
    4.在“啟動操作”中選擇“啟動外部程序”,並指明NUnit程序的運行路徑。
    5.在啟動選項中的“工作目錄”下,指明當前類庫項目的DLL文件的所在路徑。

2 

    《圖2》
    6.運行當前類庫項目,我們會發現NUnit被啟動起來了。

三、安裝Unit與使用
    請到
http://www.nunit.org/download.html下載NUnit,然后雙擊安裝即可。
    
1.我們要使用NUnit對類庫組件進行測試時,一般我們會新建一個測試類文件或新建一個測試項目。
    2.為測試項目添加引用“nunit.framework”
    3.在測試類文件中添加using NUnit.Framework;語句
    4.在該類文件或測試項目中編寫測試代碼,然后使用NUnit運行我們的測試代碼以觀察測試結果。

四、NUnit中的常用Attribute
所有NUnit屬性都包含在Nunit.Framework命名空間里。測試項目必須引用框架的程序集,即nunit.framework.dll.

1.TestFixtureAttribute
    用來修飾測試類。這個屬性標記一個類包含了測試方法。
    被TestFixtureAttribute修飾的類需滿足以下限制
        
a.必須是一個public類型,否則NUnit不會識別它。 
        b.它必須有一個缺省的構造子,否則Nunit不能構建他。 
        c.構造子不應該有任何方面的負面影響,因為在一個對話的過程中,NUnit可能構造類多次。
 
        如:
        using System;
        using NUnit.Framework;
       [TestFixture]
        public class SuccessTests
        {
        // ...
        }

2.TestAttribute 
    用來修飾測試方法
Test屬性標記某個類的某個方法為一個測試方法,而且此類必需已經標記為一個TestFixture。
    一個測試方法的簽名定義如下: 
      
 public void MethodName()
    注意:測試方法必須沒有參數。如果程序員將測試方法標記為不正確的簽名,它不會運行。
        如:
        using System;
        using NUnit.Framework;
       [TestFixture]
        public class SuccessTests
        {
            
[Test] 
            public void 
Add()
            {
                //...
            }
        }

3.SetUpAttribute
    用來修飾方法。所屬的類必需已經標記為一個TestFixture。一個TestFixture可以僅有一個SetUp方法。如果有多個定義,TestFixture也會編譯成功,但是測試不會運行。SetUpAttribute標記的方法是在每個測試方法被調用之前來完成的。
        如:
        using System;
        using NUnit.Framework;
        [TestFixture]
        public class SuccessTests
        {
            [SetUp] 
            public void Init()
            { /* ... */ }

            [TearDown] 
            public void Dispose()
            { /* ... */ }

            [Test] 
            public void Add()
            { /* ... */ }
        }
    SetUp屬性是從任何基類繼承而來。因此,如果基類已經定義了一個SetUp方法,那么這個方法會在每個派生的類的測試方法之前調用。如果你打算在派生類里加入更多的SetUp功能,你需要將方法標記為適當的屬性,然后調用基類方法。

    SetUpAttribute使用案例:
        如:我們以測試加減法為例
        using System; 
        using NUnit.Framework; 
        [TestFixture] 
        public class NumersFixture 
        { 
                    [Test] 
                    public void AddTwoNumbers() 
                    { 
                              
 int a=1; 
                                int b=2; 
                                int sum=a+b; 
                                Assert.AreEqual(sum,3); 
                    } 
                   [Test] 
                    public void MultiplyTwoNumbers() 
                    { 
                                
int a = 1; 
                                int b = 2; 
                                int product = a * b; 
                                Assert.AreEqual(2, product); 
                    } 
        } 
        不難看出兩個測試方法中有重復的代碼,如何去除重復的代碼呢?我們可以提取這些代碼到一個獨立的方法,然后標志這個方法為SetUp 屬性,這樣2個測試方法可以共享對操作數的初始化了,這里是改動后的代碼: 
        using System; 
        using NUnit.Framework; 
        [TestFixture] 
        public class NumersFixture 
        { 
                    private int a; 
                    private int b; 
                 
 [SetUp] 
                    public void InitializeOperands() 
                    { 
                              
 a = 1; 
                                b = 2;
 
                    }

                    [Test] 
                    public void AddTwoNumbers() 
                    { 
                                
int sum=a+b; 
                                Assert.AreEqual(sum,3); 
                    } 
                
   [Test] 
                    public void MultiplyTwoNumbers() 
                    { 
                                
int product = a * b; 
                                Assert.AreEqual(2, product); 
                    } 
        } 
        這樣NUnit將在執行每個測試前執行標記SetUp屬性的方法.在本例中就是執行InitializeOperands()方法.記住,這里這個方法必須為public,不然就會有以下錯誤:Invalid Setup or TearDown method signature


4.TearDownAttribute 
   用來修飾方法所屬的類必需已經標記為一個TestFixture。一個TestFixture可以僅有一個TearDown方法。如果有多個定義,TestFixture也會編譯成功,但是測試不會運行。被TearDownAttribute修飾的方法是每個測試方法被調用之后來執行的。
        如:
        using System;
        using NUnit.Framework;
        
[TestFixture]
        public class SuccessTests
        {
            [SetUp] 
            public void Init()
            { /* ... */ }

           [TearDown] 
            public void Dispose()
            { /* ... */ }

            [Test] 
            public void Add()
            { /* ... */ }
        }
    TearDown屬性是從任何的基類繼承而來。因此,如果基類已經定義了一個TearDown方法,那么這個方法會在每個派生的類的測試方法之后調用。如果你打算在派生類里加入更多的TearDown功能,你需要將方法標記為適當的屬性,然后調用基類方法。

5.TestFixtureSetUpAttribute 
    用來修飾方法。所屬的類必需已經標記為一個TestFixture。這些個屬性標記的方式在fixture任何測試執行之前完成。TestFixture可以僅有一個TestFixtureSetUp方法。如果定義了多個,TestFixture可以成功編譯,但是測試不會被執行。

6.TestFixtureTearDownAttribute
    用來修飾方法。所屬的類必需已經標記為一個TestFixture。這些個屬性標記的方式在fixture任何測試執行之后完成。TestFixture可以僅有一個TestFixtureTearDownAttribute方法。如果定義了多個,TestFixture可以成功編譯,但是測試不會被執行。
        如:
        namespace NUnit.Tests
        {
          using System;
          using NUnit.Framework;

          [TestFixture]
          public class SuccessTests
          {
         
 [TestFixtureSetUp] 
            public void Init()
            { /* ... */ }

            [TestFixtureTearDown] 
            public void Dispose()
            { /* ... */ }

            [Test] 
            public void Add()
            { /* ... */ }
          }
        }

    SetUp/TearDown方法提供達到測試隔離性的目的.SetUp確保共享的資源在每個測試運行前正確初始化,TearDown確保沒有運行測試產生的遺留副作用. TestFixtureSetUp/TestFixtureTearDown同樣提供相同的目的,但是卻在test fixture范圍里
    我們寫一個簡單的測試來說明什么方法調用了,怎么合適調用
        using System; 
        using NUnit.Framework; 
        [TestFixture] 
        public class LifeCycleContractFixture 
        { 
            
[TestFixtureSetUp] 
            public void FixtureSetUp() 
            { 
                Console.Out.WriteLine("FixtureSetUp");
            }
          
 [TestFixtureTearDown]
            public void FixtureTearDown()
            {
                Console.Out.WriteLine("FixtureTearDown");
            }
            
[SetUp]
            public void SetUp()
            {
                Console.Out.WriteLine("SetUp");
            }
            
[TearDown]
            public void TearDown()
            {
                Console.Out.WriteLine("TearDown");
            }
         
 [Test]
            public void Test1()
            {
                Console.Out.WriteLine("Test 1");
            }
        
   [Test]
            public void Test2()
            {
                Console.Out.WriteLine("Test 2");
            }
        }
        運行結果:
        FixtureSetUp
        SetUp
        Test 1
        TearDown
        SetUp
        Test 2
        TearDown
        FixtureTearDown
    
7.ExpectedExceptionAttribute
    修飾方法,用來測試一個方法是否拋出了指定的異常。本屬性有兩種重載方式。第一種是一個Type,此Type為期望的異常的精確類型。 第二種是一個期望的異常全名的字符串

    在執行測試時,如果它拋出了指定的異常,那么測試通過。如果拋出一個不同的異常,測試就失敗。如果拋出了一個由期望異常繼承而來的異常,這也是成功的。
        using System;
        using NUnit.Framework;
      
 [TestFixture]
        public class SuccessTests
        {
         
 [Test]
          
 [ExpectedException(typeof(InvalidOperationException))]
            public void ExpectAnExceptionByType()
            { /* ... */ }

            [Test]
            [ExpectedException("System.InvalidOperationException")]
            public void ExpectAnExceptionByName()
            { /* ... */ }
        }
        
8.CategoryAttribute 
    
修飾方法或修飾類。用來把測試分組,可以使用NUnit的Categories選項卡選擇要測試的組,或排除一些組。
    對類分組:
        using System;
        using NUnit.Framework;
      
 [TestFixture]
        [Category("LongRunning")]
        public class LongRunningTests
        {
        // ...
        }
    對方法分組:
        using System;
        using NUnit.Framework;
      
 [TestFixture]
        public class SuccessTests
        {
            
[Test]
            [Category("Long")]
            public void VeryLongTest()
            { /* ... */ }
        }

    下面我們編寫三個測試方法,並分為兩組“Compare”和“TestNull”,在NUnit中測試“Compare”組的內容:
    第一步:點擊左側的“Categories”選項卡
    第二步:在“Available Categories”列表框中選擇“Compare”,點擊“Add”按鈕
    第三步:點擊左側“Test”選項卡,點擊樹狀目錄中的“Class1”,點擊“Run”按鈕
    我們發現只有TestTowInstanceName和TestTowInstanceEqual兩個測試方法運行了,而TestNull沒有運行,因此TestNull不是“Compare”組的。

3
    《圖3》

4
《圖4》

9.ExplicitAttribute
    用來修飾類或方法。Explicit屬性會忽略一個測試或測試Fixture,直到它被顯式的選擇運行。。如果test和test fixture在執行的過程中被發現,就忽略他們。所以,這樣一來進度條顯示為黃色,因為有test或test fixture忽略了。
    修飾類:
        using System;
        using NUnit.Framework;
        [TestFixture, Explicit]
        public class ExplicitTests
        {
        // ...
        }
    修飾方法:
        using System;
        using NUnit.Framework;

        [TestFixture]
        public class SuccessTests
        {
          
 [Test, Explicit]
            public void ExplicitTest()
            { /* ... */ }
        }
    
10.IgnoreAttribute
    用來修飾類或方法。由於種種原因,有一些測試我們不想運行.當然,這些原因可能包括你認為這個測試還沒有完成,這個測試正在重構之中,這個測試的需求不是太明確.但你有不想破壞測試,不然進度條可是紅色的喲.怎么辦?使用Ignore屬性.你可以保持測試,但又不運行它們。
    這個特性用來暫時不運行一個測試或fixture。比起注釋掉測試或重命名方法,這是一個比較好的機制,因為測試會和余下的代碼一起編譯,而且在運行時有一個不會運行測試的標記,這樣保證不會忘記測試。
    修飾類:
        using System;
        using NUnit.Framework;
      
 [TestFixture]
        [Ignore("Ignore a fixture")]
        public class SuccessTests
        {
        // ...
        }

    修飾方法
        using System;
        using NUnit.Framework;

        [TestFixture]
        public class SuccessTests
        {
            
[Test]
            [Ignore("Ignore a test")]
            public void IgnoredTest()
            { /* ... */ }
        }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM