zoukankan      html  css  js  c++  java
  • 浅述NUnit单元测试以为BubbleSort编写单元测试为例

      写这篇博文的目的是给大家分享,如何使用NUnit为我们的.NET应用程序编写单元测试,文章假设读者没有使用过NUnit的新手,如果你是老手,可以跳过本文。如果你对NUnit还不是很了解的话,我建议你还是阅读一下。

    首先介绍几个概念。

    1.NUnit的介绍

      NUnit是一个单元测试框架,专门针对于.NET来写的。其实在前面有JUnit(Java),CPPUnit(C++),他们都是xUnit的一员。最初,它是从JUnit而来.现在的版本是2.6.接下来我所用的都是基于这个版本。
      NUnit最初是由James W. Newkirk,Alexei A. Vorontsov 和Philip A. Craig,后来开发团队逐渐庞大起来.在开发过程中, Kent Beck 和Erich Gamma2位也提供了许多帮助。看来对于NUnit还真是下了一番力气了。
      NUnit是xUnit家族种的第4个主打产品,完全由C#语言来编写,并且编写时充分利用了许多.NET的特性,比如反射,客户属性等等。
      最重要的一点是它适合于所有.NET语言。如果你还没有下载,可以到http://www.nunit.org/去下载。(文件很小,大概3点几M吧)

    1.1NUnit常用属性

    TestFixture     

    本属性标记一个类包含测试.做为一个测试的类,这个类还有一些限制:
     1.必须是Public,否则NUnit看不到它的存在.
     2.它必须有一个缺省的构造函数,否则是NUnit不会构造它.
     3.构造函数应该没有任何副作用,因为NUnit在运行时经常会构造这个类多次,如果要是构造函数有什么副作用的话,那不是乱了。

    Test    

    Test属性用来标记一个类(已经标记为TestFixture)的某个方法是可以测试的.
     1.测试方法必须为Public.
     2.测试方法必须没有参数.
     3.测试方法不返回任何参数.

    SetUp/TearDown 

    用于在测试开始时初始化,和测试后清除.标记为SetUp/TearDown 属性方法必须为public。

    ExpectedException

    这里是一个验证这个假设的测试.在这个属性里,你可以在执行过程中捕获你期望的异常类型.如果这个方法在没有抛出期望异常的情况下完成了,这个测试失败.使用这个属性帮助我们写程序员测试验证边界条件(Boundary Conditions).
    Ignore

    由于种种原因,有一些测试我们不想运行.当然,这些原因可能包括你认为这个测试还没有完成,这个测试正在重构之中,这个测试的需求不是太明确.但你有不想破坏测试,不然进度条可是红色的哟.怎么办?使用Ignore属性.你可以保持测试,但又不运行它们.

    TestFixtureSetUp/TestFixtureTearDown 
    有时,一组测试需要的资源太昂贵.例如,数据库连接可能是一个关键资源,在一个test fixture的每个测试中,打开/关闭数据库连接可能非常慢.这就是我在开始提到的问题.如何解决?NUnit有一对类似于前面讨论的SetUp/TearDown的属性: TestFixtureSetUp/TestFixtureTearDown.正如他们名字表明的一样,这些属性用来标记为整个test fixture初始化/释放资源方法一次的方法。例如,如果你想为所有test fixture的测试共享相同的数据库连接对象,我们可以写一个打开数据库连接的方法,标记为TestFixtureSetUp属性,编写另外一个关闭数据库连接的方法,标记为TestFixtureTearDown属性。

    Explicit
    本属性忽略一个test和test fixture,直到它们显式的选择执行。如果test和test fixture在执行的过程中被发现,就忽略他们。所以,这样一来进度条显示为黄色,因为有test或test fixture忽略了。
    Category

    对于测试来说,你有的时候需要将之分类,此属性正好就是用来解决这个问题的。

    测试生命周期
      FixtureSetUp

    loop:
       SetUp
         Test Method1
       TearDown
       SetUp
         Test Method2
       TearDown

    end loop
    FixtureTearDown

     
    NUnit是在.NET进行TDD的利器。

    2.TDD的简介

      测试驱动开发,英文全称Test-Driven Development,简称TDD,是一种不同于传统软件开发流程的新型的开发方法。它要求在编写某个功能的代码之前先编写测试代码,然后只编写使测试通过的功能代码,通过测试来推动整个开发的进行。这有助于编写简洁可用和高质量的代码,并加速开发过程。

      Kent Beck先生最早在其极限编程(XP)方法论中,向大家推荐“测试驱动”这一最佳实践,还专门撰写了《测试驱动开发》一书,详细说明如何实现。经过几年的迅猛发展,测试驱动开发已经成长为一门独立的软件开发技术,其名气甚至盖过了极限编程。

    测试驱动开发的基本思想就是在开发功能代码之前,先编写测试代码,然后只编写使测试通过的功能代码,从而以测试来驱动整个开发过程的进行。这有助于编写简洁可用和高质量的代码,有很高的灵活性和健壮性,能快速响应变化,并加速开发过程。 

      测试驱动开发的基本过程如下: 

      ① 快速新增一个测试 

      ② 运行所有的测试(有时候只需要运行一个或一部分),发现新增的测试不能通过 

      ③ 做一些小小的改动,尽快地让测试程序可运行,为此可以在程序中使用一些不合情理的方法 

      ④ 运行所有的测试,并且全部通过 

      ⑤ 重构代码,以消除重复设计,优化设计结构 

      简单来说,就是不可运行/可运行/重构——这正是测试驱动开发的口号。 

     3.VS2010下使用NUnit 2.6编写单元测试示例

     首先,新建一个vs2010工程,我选择了控制台程序模板,为工程添加一个新的类:Calculator。累的内容为实现的一个BubbleSort排序。实现如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace NunitTestBubbleSort
    {   
        public class Calculator
        {
            /// <summary>
            /// BubbleSort
            /// </summary>
            /// <param name="array"></param>
            /// <returns></returns>
            public int[] BubbleSort(int[] array)
            {
                if (array == null)
                {
                    return new int[] { };
                }
    
                for (int i = 0; i < array.Length - 1; i++)//n-1次
                  {
                  bool swap = false;//标识
                    for (int j = 0; j < array.Length - 1 - i; j++)//每次比较过程
                    {
                        if (array[j] > array[j + 1])
                        {
                            int temp = array[j];
                            array[j] = array[j + 1];
                            array[j + 1] = temp;
    
                            swap = true;
                        }                  
                    }
                    if (!swap)
                    {
                        return array;
                    }
                }
                return array;
            }
            /*
             * 
             * 
             * 
             * 
             */
    
    
        }
    }

     然后,我们为工程添加一个测试类:CalculatorTest。这时,我们需要添加一个引用:nunit.framework;并在CalculatorTest类中添加名称空间:using CalculatorTest,如下:

     这样我们就可以开始编写我们的测试类CalculatorTest了,做一个简单的测试case如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using NUnit.Framework;//引用这个名称空间
    
    namespace NunitTestBubbleSort
    {
        [TestFixture]
        public class CalculatorTest
        {
            [TestFixtureSetUp]
            public void FirstInit()
            { 
                //
            }
            [SetUp]
            public void Init()
            { 
                //
            }
            [TearDown]
            public void Dispose()
            { 
                //
            }
            [TestFixtureTearDown]
            public void LastDispose()
            { 
                //
            }
    
            [Test]
            public void BubbleSortTest()
            {
                int[] arr = new int[] { 9, 8, 77, -10, 0 };
    
                int[] expect=new  int[]{-10,0,8,9,77};
    
                Calculator ca = new Calculator();
                int[] result = ca.BubbleSort(arr);
                Assert.AreEqual(expect, result);
            }
    
            [Test ,Explicit ]
            public void BubbleSortTest2()
            {
                int[] arr = null;
                int[] expect = new int[] { };
    
                Calculator ca = new Calculator();
                int[] result = ca.BubbleSort(arr);
                Assert.AreEqual(expect, result);
            }
        }
    }

    然后,打开NUnit工具,Open刚生成的PE文件。RUN之。效果如下:

    绿色,代表我们的测试通过。

    关于NUnit的进一步讲解,请期待下集。

    请点击下面的“绿色通道”----“关注DebugLZQ”,共同交流进步~

  • 相关阅读:
    AD20改变pcb图纸大小方式
    ceph相关概念
    五种IO模型和三种实现方式
    MongoDB入门
    GO通过sqlx库操作MySQL
    Go原生sql操作MySQL
    Traefik工作原理
    Redis主从
    Nginx入门
    Redis入门
  • 原文地址:https://www.cnblogs.com/DebugLZQ/p/2581537.html
Copyright © 2011-2022 走看看