首页  ·  知识 ·  编程语言
NUnit2.0详细使用方法(3)
www.LiTianPing.com  http://www.cnblogs.com/ltp/archive/2005/12/03/2897  .NET  编辑:dezai  图片来源:网络
1using System; 2using NUnit.Framework; 3 4namespace NUnitQuickStart 5{ 6

 1using System;
 2using NUnit.Framework;
 3 
 4namespace NUnitQuickStart
 5{
 6            [TestFixture]
 7            public class NumersFixture
 8            {
 9                        [Test]
10                        public void AddTwoNumbers()
11                        {
12                                    int a=1;
13                                    int b=2;
14                                    int sum=a+b;
15                                    Assert.AreEqual(sum,3);
16                        }
17                        [Test]
18                        public void MultiplyTwoNumbers()
19                        {
20                                    int a = 1;
21                                    int b = 2;
22                                    int product = a * b;
23                                    Assert.AreEqual(2, product);
24                        }
25 
26            }
27}
28   我们仔细一看,不对,有重复的代码,如何去除重复的代码呢?我们可以提取这些代码到一个独立的方法,然后标志这个方法为SetUp 属性,这样2个测试方法可以共享对操作数的初始化了,这里是改动后的代码:
 1using System;
 2using NUnit.Framework;
 3 
 4namespace NUnitQuickStart
 5{
 6            [TestFixture]
 7            public class NumersFixture
 8            {
 9                        private int a;
10                        private int b;
11                        [SetUp]
12                        public void InitializeOperands()
13                        {
14                                    a = 1;
15                                    b = 2;
16                        }
17 
18                        [Test]
19                        public void AddTwoNumbers()
20                        {
21                                    int sum=a+b;
22                                    Assert.AreEqual(sum,3);
23                        }
24                        [Test]
25                        public void MultiplyTwoNumbers()
26                        {
27                                    int product = a * b;
28                                    Assert.AreEqual(2, product);
29                        }
30 
31            }
32}
33
   这样NUnit将在执行每个测试前执行标记SetUp属性的方法.在本例中就是执行InitializeOperands()方法.记住,这里这个方法必须为public,不然就会有以下错误:Invalid Setup or TearDown method signature


ExpectedException
这里是一个验证这个假设的测试.有的时候,我们知道某些操作会有异常出现,例如, 在实例中增加除法,某个操作被0除,抛出的异常和.NET文档描述的一样.参看以下源代码.
1[Test]2[ExpectedException(typeof(DivideByZeroException))]3public void DivideByZero()4{5   int zero = 0;6   int infinity = a/zero;7   Assert.Fail("Should have gotten an exception");8}9

   除了[Test]属性之外, DivideByZero方法有另外一个客户属性: ExpectedException.在这个属性里,你可以在执行过程中捕获你期望的异常类型,例如在本例就是DivideByZeroException.如果这个方法在没有抛出期望异常的情况下完成了,这个测试失败.使用这个属性帮助我们写程序员测试验证边界条件(Boundary Conditions).
Ignore 属性
   由于种种原因,有一些测试我们不想运行.当然,这些原因可能包括你认为这个测试还没有完成,这个测试正在重构之中,这个测试的需求不是太明确.但你有不想破坏测试,不然进度条可是红色的哟.怎么办?使用Ignore属性.你可以保持测试,但又不运行它们.让我们标记MultiplyTwoNumbers测试方法为Ignore属性:
1[Test]2[Ignore("Multiplication is ignored")]3public void MultiplyTwoNumbers()4{5   int product = a * b;6   Assert.AreEqual(2, product);7}
运行测试,现在产生了下面的输出(在图5-1显示):

 
图 5-1: 在一个程序员测试中使用 Ignore属性
   Ignore属性可以附加到一个独立的测试方法,也可以附加到整个测试类(TestFixture).如果Ignore属性附加到TestFixture,所有在fixture的测试都被忽略.

TestFixtureSetUp/TestFixtureTearDown

   有时,一组测试需要的资源太昂贵.例如,数据库连接可能是一个关键资源,在一个test fixture的每个测试中,打开/关闭数据库连接可能非常慢.这就是我在开始提到的问题.如何解决?NUnit有一对类似于前面讨论的SetUp/TearDown的属性: TestFixtureSetUp/TestFixtureTearDown.正如他们名字表明的一样,这些属性用来标记为整个test fixture初始化/释放资源方法一次的方法.
   例如,如果你想为所有test fixture的测试共享相同的数据库连接对象,我们可以写一个打开数据库连接的方法,标记为TestFixtureSetUp属性,编写另外一个关闭数据库连接的方法,标记为TestFixtureTearDown属性.这里是描述这个的例子. using NUnit.Framework; 2 3[TestFixture] 4public class DatabaseFixture 5{ 6   [TestFixtureSetUp] 7   public void OpenConnection() 8   { 9      //open the connection to the database10   }11 12   [TestFixtureTearDown]13   public void CloseConnection()14   {15      //close the connection to the database16   }17   18   [SetUp]19   public void CreateDatabaseObjects()20   {21      //insert the records into the database table22   }23 24   [TearDown]25   public void DeleteDatabaseObjects()26   {27      //remove the inserted records from the database table28   }29 30   [Test]31   public void ReadOneObject()32   {33      //load one record using the open database connection34   }35 36   [Test]37   public void ReadManyObjects()38   {39      //load many records using the open database connection40   }41}4243
Test Suite
   Test Suite是test case或其他test suite的集合. 合成(Composite),模式描述了test case和test suite之间的关系.
 参考来自NUnit的关于Suite的代码
Suite Attribute
 1namespace NUnit.Tests
 2{
 3using System;
 4  using NUnit.Framework;
 5
 6
 7
 8  public class AllTests
 9  {
10    [Suite]
11    public static TestSuite Suite
12    {
13      get
14      {
15        TestSuite suite = new TestSuite("All Tests");
16        suite.Add(new OneTestCase());
17        suite.Add(new Assemblies.AssemblyTests());
18        suite.Add(new AssertionTest());
19        return suite;
20      }
21    }
22  }
23}
24Category属性
 对于测试来说,你有的时候需要将之分类,此属性正好就是用来解决这个问题的。
 你可以选择你需要运行的测试类目录,也可以选择除了这些目录之外的测试都可以运行。在命令行环境里 /include 和/exclude来实现。在GUI环境下,就更简单了,选择左边工作域里的Catagories Tab,选择Add和Remove既可以了。
在上面的例子上做了一些改善,代码如下:
 1using System;  2using NUnit.Framework;  3   4namespace NUnitQuickStart  5{  6            [TestFixture]  7            public class NumersFixture  8            {  9                        private int a; 10                        private int b; 11                        [SetUp] 12                        public  void InitializeOperands() 13                        { 14                                    a = 1; 15                                    b = 2; 16                        } 17  18                        [Test] 19                        [Category("Numbers")] 20                        public void AddTwoNumbers() 21                        { 22                                    int sum=a+b; 23                                    Assert.AreEqual(sum,3); 24                        } 25                        26                        [Test] 27                [Category("Exception")] 28                        [ExpectedException(typeof(DivideByZeroException))] 29                        public void DivideByZero() 30                        { 31                                    int zero = 0; 32                                    int infinity = a/zero; 33                                    Assert.Fail("Should have gotten an exception"); 34                        } 35                        [Test] 36                        [Ignore("Multiplication is ignored")] 37                        [Category("Numbers")] 38                        public void MultiplyTwoNumbers() 39                        { 40                                    int product = a * b; 41                                    Assert.AreEqual(2, product); 42                        } 43  44               } 45
NUnit-GUI界面如图5-2:

 

图5-2:使用Catagories属性的界面

Explicit属性

本属性忽略一个test和test fixture,直到它们显式的选择执行。如果test和test fixture在执行的过程中被发现,就忽略他们。所以,这样一来进度条显示为黄色,因为有test或test fixture忽略了。
 例如:
  
 1
 2                        [Test,Explicit] 
 3                        [Category("Exception")] 
 4                        [ExpectedException(typeof(DivideByZeroException))] 
 5                        public void DivideByZero() 
 6                        
 7                                    int zero = 0
 8                                    int infinity = a/zero; 
 9                                    Assert.Fail("Should have gotten an exception"); 
10                        }

11
    为什么会设计成这样呢?原因是Ingore属性忽略了某个test或test fixture,那么他们你再想调用执行是不可能的。那么万一有一天我想调用被忽略的test或test fixture怎么办,就用Explicit属性了。我想这就是其中的原因吧。

Expected Exception属性

  期望在运行时抛出一个期望的异常,如果是,则测试通过,否则不通过。
参看下面的例子:
 1[Test] 
 2[ExpectedException(typeofInvalidOperationException))] 
 3public void ExpectAnException() 
 4 
 5   int zero = 0
 6   int infinity = a/zero; 
 7   Assert.Fail("Should have gotten an exception"); 
 8                       
 9 }
 
10
    在本测试中,应该抛出DivideByZeroException,但是期望的是InvalidOperationException,所以不能通过。如果我们将[ExpectedException(typeof(InvalidOperationException))]改为[ExpectedException(typeof(DivideByZeroException))],本测试通过。

5 . 测试生命周期合约

   如果记得test case的定义,其中一个属性是测试的独立性或隔离性.SetUp/TearDown方法提供达到测试隔离性的目的.SetUp确保共享的资源在每个测试运行前正确初始化,TearDown确保没有运行测试产生的遗留副作用. TestFixtureSetUp/TestFixtureTearDown同样提供相同的目的,但是却在test fixture范围里,我们刚才描述的内容组成了测试框架的运行时容器(test runner)和你写的测试之间的生命周期合约(life-cycle contract).
   为了描述这个合约,我们写一个简单的测试来说明什么方法调用了,怎么合适调用的.这里是代码:
 1using System;
 2using NUnit.Framework;
 3[TestFixture]
 4public class LifeCycleContractFixture
 5{
 6   [TestFixtureSetUp]
 7   public void FixtureSetUp()
 8   {
 9      Console.Out.WriteLine("FixtureSetUp");
10   }

11 
12   [TestFixtureTearDown]
13   public void FixtureTearDown()
14   {
15      Console.Out.WriteLine("FixtureTearDown");
16   }

17   
18   [SetUp]
19   public void SetUp()
20   {
21      Console.Out.WriteLine("SetUp");
22   }

23
24   [TearDown]
25   public void TearDown()
26   {
27      Console.Out.WriteLine("TearDown");
28   }

29 
30   [Test]
31   public void Test1()
32   {
33      Console.Out.WriteLine("Test 1");
34   }

35
36   [Test]
37   public void Test2()
38   {
39      Console.Out.WriteLine("Test 2");
40   }

41
42}

43
44
   当编译和运行这个测试,可以在System.Console窗口看到下面的输出:
FixtureSetUp
SetUp
Test 
1
TearDown
SetUp
Test 
2
TearDown
FixtureTearDown
   可以看到, SetUp/TearDown方法调用在每个测试方法的前后. 整个fixture调用一次TestFixtureSetUp/TestFixtureTearDown方法.
  作者:Milestone
 下载:
1)NUnit的应用文档 下载
2)本问的PDF版 下载
3)源代码 下载 
本文作者:www.LiTianPing.com 来源:http://www.cnblogs.com/ltp/archive/2005/12/03/2897
CIO之家 www.ciozj.com 微信公众号:imciow
   
免责声明:本站转载此文章旨在分享信息,不代表对其内容的完全认同。文章来源已尽可能注明,若涉及版权问题,请及时与我们联系,我们将积极配合处理。同时,我们无法对文章内容的真实性、准确性及完整性进行完全保证,对于因文章内容而产生的任何后果,本账号不承担法律责任。转载仅出于传播目的,读者应自行对内容进行核实与判断。请谨慎参考文章信息,一切责任由读者自行承担。
延伸阅读