写这篇博文的目的是给大家分享,如何使用NUnit为我们的.NET应用程序编写单元测试,文章假设读者没有使用过NUnit的新手,如果你是老手,可以跳过本文。如果你对NUnit还不是很了解的话,我建议你还是阅读一下。
首先介绍几个概念。
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
测试驱动开发,英文全称Test-Driven Development,简称TDD,是一种不同于传统软件开发流程的新型的开发方法。它要求在编写某个功能的代码之前先编写测试代码,然后只编写使测试通过的功能代码,通过测试来推动整个开发的进行。这有助于编写简洁可用和高质量的代码,并加速开发过程。
Kent Beck先生最早在其极限编程(XP)方法论中,向大家推荐“测试驱动”这一最佳实践,还专门撰写了《测试驱动开发》一书,详细说明如何实现。经过几年的迅猛发展,测试驱动开发已经成长为一门独立的软件开发技术,其名气甚至盖过了极限编程。
测试驱动开发的基本思想就是在开发功能代码之前,先编写测试代码,然后只编写使测试通过的功能代码,从而以测试来驱动整个开发过程的进行。这有助于编写简洁可用和高质量的代码,有很高的灵活性和健壮性,能快速响应变化,并加速开发过程。
测试驱动开发的基本过程如下:
① 快速新增一个测试
② 运行所有的测试(有时候只需要运行一个或一部分),发现新增的测试不能通过
③ 做一些小小的改动,尽快地让测试程序可运行,为此可以在程序中使用一些不合情理的方法
④ 运行所有的测试,并且全部通过
⑤ 重构代码,以消除重复设计,优化设计结构
简单来说,就是不可运行/可运行/重构——这正是测试驱动开发的口号。
首先,新建一个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”,共同交流进步~