Tony Gong的技术Blog  
技术旅途中蹒跚的行者
本章主要讲解NUnit的几个Attribute(特性)的用法。

1,TestFixture
Imports NUnit.Framework

<TestFixture()> _
Public Class Class1Test
    
Public Sub New()

    
End Sub

end class
上面代码中的<TestFixture()>就是一个特性(C#中使用[TestFixture]),这个特性告诉NUnit:
这个类包含了测试代码,你需要给我看一下。然后NUnit就到这个类里面去看看是否有需要他出马的机会。

2,Test
     <Test()> _
     
Public Sub FindMaxTest()
         
'定义一个数组
         Dim list1 As Int32() = {13104}
 
         
Dim my As New Class1
         
'测试数组list1中的最大整数是不是10。
         Assert.AreEqual(4, my.FindMax(list1))
     
End Sub

这里的<Test()>(C#中为[Test]),这个特性告诉NUnit:
这是一个需要测试的方法,你给我测试一下,并用颜色告诉我结果(红色说明测试失败,绿色说明测试成功)。
对应到NUnit的gui中如下图:

图中左边那个灰色的圆点(FindMaxTest)就是由Test特性标示出来的一个需要测试的方法,然后我们可以通过按“Run”来运行这个测试,NUnit将通过颜色来返回。

这是NUnit最主要的2个Attribute,有了这2个,就可以编写单元测试了。



除了这2个Attribute之外,还有一些其他的Attribute,可以提供给我们更强大的功能,下面列出一些常用的:
 

标识测试类

TestFixture

标识测试方法

Test

标识测试类初始化函数

TestFixtureSetup

标识测试类资源释放函数

TestFixtureTearDown

标识测试用例初始化函数

Setup

标识测试用例资源释放函数

TearDown

标识忽略该测试方法

Ignore

标识该用例所期望抛出的异常

ExpectedException

标识测试用例的分类

Category


让我们接下去讲解其他Attribute:
3,TestFixtureSetup和TestFixtureTearDown
TestFixtureSetup这个特性的作用是为整个测试类初始化一些资源,准备好测试环境,然后给该测试类的几个测试(Test)使用,而TestFixtureTearDown则是把TestFixtureSetup初始化的一些资源释放掉。
我们可以通过下面这个例子来更好的理解:

Imports NUnit.Framework

<TestFixture()> _
Public Class Class1Test
    
Private con As Connection

    
<TestFixtureSetUp()> _
    
Public Sub MyFixtureSetUp()
        
'打开数据库联接
        conn = New Connection("sqlXXX", user, password)
        conn.open()
    
End Sub


    
<TestFixtureTearDown()> _
    
Public Sub MyFixtureTearDown()
        
'关闭数据库联接
        conn.close()
    
End Sub



    
<Test()> _
    
Public Sub Mytest1()
        
'使用conn作某些测试
    End Sub


    
<Test()> _
    
Public Sub Mytest2()
        
'使用conn作某些测试
    End Sub


End Class

当你用NUnit测试Mytest1,Mytest2这2个test时,程序的运行顺序是这样的:
MyFixtureSetUp(初始化测试环境)
Mytest1(test1)
Mytest2(test2)
TestFixtureTearDown(释放资源)

4,Setup和TearDown
这2个特性和TestFixtureSetup,TestFixtureTearDown有点类似,区别在于:
Setup将在每个test之前运行,TearDown将在每个test之后运行。简单的说TestFixtureSetup,TestFixtureTearDown在一个测试类中之会运行一次;而Setup和TearDown,这个测试类有几个test被测试,就将运行几次。
举例说明:
Imports NUnit.Framework

<TestFixture()> _
Public Class Class1Test
    
Private con As Connection

    
<SetUp()> _
    
Public Sub MyFixtureSetUp()
        
'打开数据库联接
        conn = New Connection("sqlXXX", user, password)
        conn.open()
    
End Sub


    
<TearDown()> _
    
Public Sub MyFixtureTearDown()
        
'关闭数据库联接
        conn.close()
    
End Sub



    
<Test()> _
    
Public Sub Mytest1()
        
'使用conn作某些测试
    End Sub


    
<Test()> _
    
Public Sub Mytest2()
        
'使用conn作某些测试
    End Sub


End Class

当你用NUnit测试Mytest1,Mytest2这2个test时,程序的运行顺序是这样的:
SetUp(初始化测试环境)
Mytest1(test1)
TearDown(释放资源)
SetUp(初始化测试环境)
Mytest2(test2)
TearDown(释放资源)

可以看出,每个test前后都运行了SetUp和TearDown

对3和4这2组特性的选择,我个人在实际使用中感觉差别不大,随便用哪种都行,2种都用也无不可。我一般是用TestFixtureSetup和TestFixtureTearDown,一次性把资源都设置好,然后再一次性释放,写起来方便

5,Ignore
临时忽略一些test。
在以下情况可能会用到:
(1),你的测试用例写好了,但实际代码却还没完成,这样的话测试肯定是不能通过的,但是你又不想看到NUnit抛出一个红灯笼,你就可以暂时用Ignore忽略掉这个test。NUnit会抛出一个黄灯,提醒你这个测试被忽略了。(不过,抛出个红灯笼也有好处的,它能鞭策你快点写好代码,哈哈)
(2),有些测试可能耗费非常长的时间(比如几个小时),你展示不想测试它们,而想等半夜再测试,你就可以暂时Ignore它们。(不过,推荐用Category特性来把这些长时间测试分类出来,而不是用Ignore,这个将在后面讲到)

实例说明:
     <Test(), Ignore("Not Ready")> _
     
Public Sub FindMaxTest()
         
'定义一个数组
         Dim list1 As Int32() = {13104}
 
         
Dim my As New Class1
         
'测试数组list1中的最大整数是不是10。
         Assert.AreEqual(10, my.FindMax(list1))
     
End Sub

(C#中为[Test,Ignore("XXX")]           )
运行NUnit,我们将看到如下结果:

 

6,ExpectedException
标识该用例所期望抛出的异常
有时候我们知道在特定条件下我们的程序将会抛出某个异常,我们就可以用ExpectedException这个特性在测试代码中验证,程序是否如我们所想的抛出了这个异常。
如,我们那个求最大值的方法,如果传进去一个空的int32数组,应该会抛出一个NullReferenceException异常,为了验证我的猜想,我写了如下测试:

     <Test()> _
     
Public Sub FindMaxTest()Sub FindMaxTest()
         
'定义一个数组
         Dim list1() As Int32 = {13104}
         
Dim list2() As Int32 = {13410}
         
Dim list3() As Int32 = {10314}
         
Dim list4() As Int32 = {-2-1-3}
 
         
Dim my As New Class1
        
'测试数组list1中的最大整数是不是10。
        Assert.AreEqual(10, my.FindMax(list1))

        
'测试边界值
        Assert.AreEqual(10, my.FindMax(list2))
        Assert.AreEqual(
10, my.FindMax(list3))

        
'测试负数数组,数组中最大值应该是-1
        Assert.AreEqual(-1, my.FindMax(list4))
    
End Sub


    
<Test(), ExpectedException(GetType(NullReferenceException))> _
    
Public Sub TestForException()
        
Dim list1() As Int32
        
Dim my As New Class1
        my.FindMax(list1)
    
End Sub


(C#中为[Test,ExpectedException(Typeof(NullReferenceExcepton))]        )
运行NUnit,如下:


果然如此,程序的确抛出了NullReferenceException。而假如系统没有如我们所料抛出异常,或者抛出的不是此类异常,NUnit则会给我们个红灯笼。

7,Category
分类。
该特性可以把一些测试分成不同的种类,比如我们前面提到的,假如有些测试很耗时,我们就可以把它们分类成LongTime测试,而把其他的测试分类成ShortTime测试,然后,我们可以在NUnit中选择只运行ShortTime的测试,那些LongTime的测试则可以在夜晚自动构建的时候运行它们。
使用举例如下:

Imports NUnit.Framework

<TestFixture()> _
Public Class Class1Test

    
<Test(), Category("ShortTime")> _
    
Public Sub Mytest1()

    
End Sub


    
<Test(), Category("ShortTime")> _
    
Public Sub Mytest2()

    
End Sub


    
<Test(), Category("LongTime")> _
    
Public Sub Mytest3()

    
End Sub


    
<Test(), Category("LongTime")> _
    
Public Sub Mytest4()

    
End Sub

End Class

(C#中为[Test][Category(“ShortTime”)]        )
这个测试类中有2种测试方法:ShortTime和LongTime,
运行NUnit,选择"Categories",我们将看到,Available Categories中看到有2种分类,选择“shortTime”,然后运行,只有ShortTime的那些测试方法被运行了。



除了这些Attribute之外,其实还有一些,不过我在实际使用中很少用到,我就不拿出来讲了。

下篇学习笔记,我将列举几种单元测试与项目结合的方法。

posted on 2006-04-28 15:50  Tony.Gong  阅读(2106)  评论(3编辑  收藏  举报