TestFixtureSetUp/TestFixtureTearDown
有时,一组测试需要的资源太昂贵.例如,数据库连接可能是一个关键资源,在一个test fixture的每个测试中,打开/关闭数据库连接可能非常慢.这就是我在开始提到的问题.如何解决?NUnit有一对类似于前面讨论的
SetUp/
TearDown的属性:
TestFixtureSetUp/
TestFixtureTearDown.正如他们名字表明的一样,这些属性用来标记为整个test fixture初始化/释放资源方法一次的方法.
例如,如果你想为所有test fixture的测试共享相同的数据库连接对象,我们可以写一个打开数据库连接的方法,标记为
TestFixtureSetUp属性,编写另外一个关闭数据库连接的方法,标记为
TestFixtureTearDown属性.这里是描述这个的例子.
1
using
NUnit.Framework;
2
3
[TestFixture]
4
public
class
DatabaseFixture
5
{ 6 [TestFixtureSetUp] 7 public void OpenConnection() 8 { 9 //open the connection to the database 10 } 11 12 [TestFixtureTearDown] 13 public void CloseConnection() 14 { 15 //close the connection to the database 16 } 17 18 [SetUp] 19 public void CreateDatabaseObjects() 20 { 21 //insert the records into the database table 22 } 23 24 [TearDown] 25 public void DeleteDatabaseObjects() 26 { 27 //remove the inserted records from the database table 28 } 29 30 [Test] 31 public void ReadOneObject() 32 { 33 //load one record using the open database connection 34 } 35 36 [Test] 37 public void ReadManyObjects() 38 { 39 //load many records using the open database connection 40 } 41}
42
43
Test Suite
Test Suite是test case或其他test suite的集合. 合成(Composite)
,模式描述了test case和test suite之间的关系.
参考来自NUnit的关于Suite的代码
Suite Attribute
1
namespace
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}
24
Category属性
对于测试来说,你有的时候需要将之分类,此属性正好就是用来解决这个问题的。
你可以选择你需要运行的测试类目录,也可以选择除了这些目录之外的测试都可以运行。在命令行环境里 /include 和/exclude来实现。在GUI环境下,就更简单了,选择左边工作域里的Catagories Tab,选择Add和Remove既可以了。
在上面的例子上做了一些改善,代码如下:
1
using
System;
2
using
NUnit.Framework;
3
4
namespace
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忽略了。
例如:
Expected Exception属性
期望在运行时抛出一个期望的异常,如果是,则测试通过,否则不通过。
参看下面的例子:
5 . 测试生命周期合约
如果记得test case的定义,其中一个属性是测试的独立性或隔离性.
SetUp/TearDown方法提供达到测试隔离性的目的.
SetUp确保共享的资源在每个测试运行前正确初始化,
TearDown确保没有运行测试产生的遗留副作用.
TestFixtureSetUp/
TestFixtureTearDown同样提供相同的目的,但是却在test fixture范围里,我们刚才描述的内容组成了测试框架的运行时容器(test runner)和你写的测试之间的生命周期合约(
life-cycle contract).
为了描述这个合约,我们写一个简单的测试来说明什么方法调用了,怎么合适调用的.这里是代码:
1
using
System;
2
using
NUnit.Framework;
3
[TestFixture]
4
public
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 } 2324 [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 } 3536 [Test] 37 public void Test2() 38 { 39 Console.Out.WriteLine("Test 2"); 40 } 4142}
43
44
当编译和运行这个测试,可以在
System.Console窗口看到下面的输出:
FixtureSetUp SetUp Test
1