单元测试:Nunit(二)

      作为单元测试的第二部分,和第一部分的间隔时间差的的确有点长了(嘿嘿,自己一直在偷懒)。在第一讲中主要讲的是如何在VS2005中进行单元测试,以及当时选NUnit2.48(.net 2.0)作为学习的版本,和进行了一个小个程序的测试,大致上都知道如何使用NUnitC#编写的代码如何进行单元测试,而在这一讲中则是主要讲讲几个常用的属性(Attribute)

先写一个小小的程序,功能只是在一个数组中找出一个最大的数字。

代码
        public int GetLargest(int[] array)
        {
            
if (null == array || 0 == array.Length)
            {
                
throw new Exception("数组为空!");
            }

            
int num = Int32.MinValue;

            
for (int i = 0; i < array.Length; i++)
            {
                
if (num < array[i])
                {
                    num 
= array[i];
                }
            }

            
return num;
         }

    同样要建立一个测试类,现在开始逐个介绍一些比较常用的属性。

    一、[TestFixtureSetUp]这个属性标识的函数表示是这个类的初始化函数,测试类一旦执行,首先执行的就是这个属性标识的函数,既然是初始化,那当然一般是初始化一些对象和字段之类的,功能有点类似于构造函数。

        [TestFixtureSetUp]
        
public void Init()
        {
            largest 
= new Largest();
            Console.WriteLine(
"我只会在类的最初调用时初始化对象!");
        }

    二、上面说了初始化,自然的我们要说到销毁了,[TestFixtureTearDown]与初始化对应,此属性标识的函数在类的最后用来销毁对象,根据功能很自然的就想到析构函数。 

代码
        [TestFixtureTearDown]
        
public void Terminate()
        {
            
if (null != largest)
            {
                largest 
= null;
            }
            Console.WriteLine(
"我只会在类的最后销毁对象!");
        }

     三、上面说的初始化和销毁都是针对整个测试类来说的,有没有一个可以针对没个测试的case的呢?可以在执行每个case之前进行初始化,在每个case执行之后又可以销毁,这样不就可以让一些公用的对象可以在执行每个case的时候都重新被赋值,不会相互影响。既然都这样说了,当然有了。[SetUp]属性标识的函数可以在每个Test Case的执行之前初始化一次。

        [SetUp]
        
public void InitCase()
        {
            largest 
= new Largest();
            Console.WriteLine(
"我会在执行每个Test Case之前初始化对象!");
        }

       四、直接来看销毁[TearDown].

代码
        [TearDown]
        
public void TerminateCase()
        {
            
if(null != largest)
            {
                largest 
= null;
            }
            Console.WriteLine(
"我会在执行完每个Test Case之后销毁对象!");
        }

    五、在程序中我们对应空数组抛出了一个异常,那么我们在测试的时候,如果输入的数组是空的会怎么样?看下面一段程序:

        [Test]
        
public void TestGetLargest1()
        {
            
int[] numArr = new int[] { };

            largest.GetLargest(numArr);
        }

    很明显,测试肯定会抛出一个异常,不能通过。

   

    那现在我们知道这样输入是不对,那怎么可以屏蔽掉这个异常呢。[ExpectedException],这个实行有几个重载的类型,根据情况自己选择。

代码
        [Test]
        [ExpectedException(
typeof(Exception))]
        
public void TestGetLargest2()
        {
            
int[] numArr = new int[] { };

            largest.GetLargest(numArr);
        }

 

    这个时候我们看到的结果不再是提示有异常抛出,而是通过了测试(你都已经预料到有这种异常了,当然不会再提示你程序会抛出这个异常!)

    六、最后简单的提一下其他几个属性:[Ignore]标识的Test Case不会再NUnitIDE中执行,因为被你忽略掉了。[Explicit]必须要显示的选中这个Case才会被执行,否则是不会执行的。[Category]分组属性,可以将几个Case分到同一个组中,这样就会以组为单位去执行,或不执行。

    测试类完整代码贴上:

代码
    [TestFixture]
    
public class LargestTest
    {
        
private Largest largest;

        [SetUp]
        
public void InitCase()
        {
            largest 
= new Largest();
            Console.WriteLine(
"我会在执行每个Test Case之前初始化对象!");
        }

        [TearDown]
        
public void TerminateCase()
        {
            largest 
= null;
            Console.WriteLine(
"我会在执行完每个Test Case之后销毁对象!");
        }

        [TestFixtureSetUp]
        
public void Init()
        {
            largest 
= new Largest();
            Console.WriteLine(
"我只会在类的最初调用时初始化对象!");
        }

        [TestFixtureTearDown]
        
public void Terminate()
        {
            
if (null != largest)
            {
                largest 
= null;
            }
            Console.WriteLine(
"我只会在类的最后销毁对象!");
        }

        [Test]
        
public void TestGetLargest()
        {
            
int[] numArr = new int[] { -1024-10 };

            
int result = largest.GetLargest(numArr);

            Assert.AreEqual(
4, result);
        }

        [Test]
        
public void TestGetLargest1()
        {
            
int[] numArr = new int[] { };

            largest.GetLargest(numArr);
        }

        [Test]
        [ExpectedException(
typeof(Exception))]
        
public void TestGetLargest2()
        {
            
int[] numArr = new int[] { };

            largest.GetLargest(numArr);
        }

        [Test]
        
public void TestGetLargest3()
        {
            
int[] numArr = new int[] { 1010 };
            
int result = largest.GetLargest(numArr);

            Assert.AreEqual(
10, result);
        }

        [Test]
        [Ignore]
        
public void TestGetLargest4()
        {
            
int[] numArr = null;

            
int result = largest.GetLargest(numArr);
        }
}

执行结果:

不知道有没有发现个问题,对于这个程序中,测试案例会很多,比如说数组的数全是正数,负数,有正有负,全部数相同时等等,这样不就要写很多重复的测试case,应该有其他的方法吧。呵呵,不妨试试利用XML、文本存储数据来实现。下一部分我准备用XML读取数据来实现。

posted @ 2010-03-15 08:47  勇者归来  阅读(384)  评论(0编辑  收藏  举报