• 单元测试: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读取数据来实现。

  • 相关阅读:
    IE盒子模型和标准W3C盒子模型
    [转载] MVC3自定义标签,给Html.ActionLink加上支持图片链接的功能
    MVC3获取登录用户名
    [转]APS.netMVC的ViewModel问题
    [转载]Js小技巧||给input type=“password”的输入框赋默认值
    [资料]aspnetdb.mdf数据库的建立和使用
    [转] .net网页中插入Flash
    [转]Membership、MembershipUser和Roles类
    [小技巧]提交按钮
    asp.net mvc中session的使用 样例
  • 原文地址:https://www.cnblogs.com/wangyong/p/1685876.html
Copyright © 2020-2023  润新知