前一段时间,有人问我在.NET里如何进行TDD开发.这个问题促使我想对NUnit做一个详细的介绍.因为我们大家都知道NUnit是在.NET进行TDD的利器.
如果你已经知道很多关于NUnit的应用,请指出我的不对之处和提出一些建议,使本文更加完善.如果你对NUnit还不是很了解的话,我建议你还是阅读一下.
本文分为以下部分:
1. TDD的简介
首先什么是TDD呢?Kent Beck在他的<<测试驱动开发 >>(Addison-Wesley Professional,2003)一书中,使用下面2个原则来定义TDD:
· 除非你有一个失败的自动测试,永远不要写一单行代码.
· 阻止重复
我想第一个原则是显而易见的.在没有失败的自动测试下就不要写代码.因为测试是嵌入在代码必须满足的需求中.如果没有需求,就没有必要实现任何东西.所以这个原则阻止我们去实现那些没有测试和在解决方案中不需要的功能.
第二个原则说明了在一个程序中,不应该包含重复的代码.如果代码重复,我想这就是不好的软件设计的象征.随着时间的流逝,它会对程序造成不一致的问题,并且使代码变非常混乱 ,因为我们时常不会记得重复代码的位置.如果发现代码重复,我想我们应该立即删除代码重复.其实这就涉及到重构了.在这里我就不多讲了.
一般来说,测试分为2种类型,一是程序员自己的测试,另外一种是客户的测试.关于客户测试,我推荐一个FIT的框架,非常不错。在这里,我们讲的TDD就是程序员测试.那么什么是程序员测试呢?我认为就是我们常说的单元测试.既然是单元测试,在.NET里势必会用到某些工具,目前最著名恐怕就是我即将介绍的NUnit了,
2.NUnit的介绍
NUnit是一个单元测试框架,专门针对于.NET来写的.其实在前面有JUnit(Java),CPPUnit(C++),他们都是xUnit的一员.最初,它是从JUnit而来.现在的版本是2.2.接下来我所用的都是基于这个版本.
NUnit最初是由James W. Newkirk, Alexei A. Vorontsov 和Philip A. Craig, 后来开发团队逐渐庞大起来.在开发过程中, Kent Beck 和Erich Gamma2位牛人也提供了许多帮助.看来对于NUnit还真是下了一番力气了.J
NUnit是xUnit家族种的第4个主打产品,完全由C#语言来编写,并且编写时充分利用了许多.NET的特性,比如反射,客户属性等等.
最重要的一点是它适合于所有.NET语言.
如果你还没有下载,可以到http://www.nunit.org/去下载.
2.1 NUnit的介绍 Ok,下面正式讲解NUnit.在讲解之前,看看几张图片:
图1 NUnit运行的效果
图2 NUnit运行的另外一个效果
从中我们可以非常容易发现,右边是个状态条,图1是红色的,图2是绿色的.为什么会这样呢?因为如果所有测试案例运行成功,就为绿色,反之如果有一个不成功,则为红色,但也有黄色的.左面的工作域内则是我们写的每一个单元测试.
通过上面的图片,我想你对NUnit有个总的了解了.
接下来还是分为2个部分,一是NUnit的布局,另外一部分就是它的核心概念.
首先熟悉一下NUnit GUI的布局.
让我们更进一步看一下测试运行器窗口的布局。在右边面板的中间,可以看到测试进度条。进度条的颜色反映了测试执行的状态:
绿色 描述目前所执行的测试都通过
黄色 意味某些测试忽略,但是这里没有失败
红色 表示有失败
底部的状态条表示下面的状态:
状态.说明了现在运行测试的状态。当所有测试完成时,状态变为Completed.运行测试中,状态是Running: <test-name> (<test-name>是正在运行的测试名称)。
Test Cases说明加载的程序集中测试案例的总个数。这也是测试树里叶子节点的个数。
Tests Run 已经完成的测试个数。
Failures 到目前为止,所有测试中失败的个数.
Time 显示运行测试时间(以秒计)
File主菜单有以下内容:
New Project允许你创建一个新工程。工程是一个测试程序集的集合。这种机制让你组织多个测试程序集,并把他们作为一个组对待。
Open 加载一个新的测试程序集,或一个以前保存的NUnit工程文件。
Close关闭现在加载的测试程序集或现在加载的NUnit工程。
Save 保存现在的Nunit工程到一个文件。如果正工作单个程序集,本菜单项允许你创建一个新的NUnit工程,并把它保存在文件里。
Save As允许你将现有NUnit工程作为一个文件保存。
Reload 强制重载现有测试程序集或NUnit工程。NUnit-Gui自动监测现加载的测试程序集的变化。
当程序集变化时,测试运行器重新加载测试程序集。(当测试正运行时,现在加载的测试程序集不会重新加载。在测试运行之间测试程序集仅可以重新加载。一个忠告:如果测试程序集依赖另外一个程序集,测试运行器不会观察任何依赖的程序集。对测试运行器来说,强制一个重载使全部依赖的程序集变化可见。
Recent Files 说明5个最近在NUnit中加载的测试程序集或NUnit工程(这个列表在Windows注册表,由每个用户维护,因此如果你共享你的PC,你仅看到你的测试)。最近程序集的数量可以使用Options菜单项修改,可以访问Tool主菜单。
Exit退出。
View菜单有以下内容:
Expand一层层扩展现在树中所选节点
Collapse 折叠现在树中选择的节点
Expand All递归扩展树中所选节点后的所有节点
Collapse All递归折叠树中所选节点后的所有节点
Expand Fixtures扩展树中所有代表测试fixture的节点。
Collapse Fixtures 折叠树中所有代表测试fixture的节点。
Properties 显示树中现所选节点的属性。
Tools 菜单由这些项:
Save Results as XML作为一XML文件保存运行测试的结果。
Options让你定制NUnit的行为。
现在看看右边,你已经熟悉Run按钮和进度条。这里还有一个紧跟Run按钮的Stop按钮:点击这个按钮会终止执行正运行的测试。进度条下面是一个文本窗口,在它上方,由以下4个标签:
Errors and Failures 窗口显示失败的测试。在我们的例子里,这个窗口是空。
Tests Not Run 窗口显示没有得到执行的测试。
Console.Error 窗口显示运行测试产生的错误消息。这些此消息是应用程序代码使用Console.Error输出流可以输出的。
Console.Out窗口显示运行测试打印到Console.Error输出流的文本消息。
2.2 一些常用属性
接下来,我将讲述这个框架如何使用.同时也涉及到一些非常重要的概念,我想其客户属性是非常重要的.在NUnit里,有以下几种属性:
下面我将对每种属性一一讲解.
TestFixtureAttribute
本属性标记一个类包含测试,当然setup和teardown方法可有可无.(关于setup 和teardown方法在后面介绍)
做为一个测试的类,这个类还有一些限制
- 必须是Public,否则NUnit看不到它的存在.
- 它必须有一个缺省的构造函数,否则是NUnit不会构造它.
- 构造函数应该没有任何副作用,因为NUnit在运行时经常会构造这个类多次,如果要是构造函数要什么副作用的话,那不是乱了.
举个例子
1 using System;
2 using NUnit.Framework;
3 namespace MyTest.Tests
4{
5
6 [TestFixture]
7 public class PriceFixture
8 {
9 //
10 }
11}
12
TestAttribute
Test属性用来标记一个类(已经标记为TestFixture)的某个方法是可以测试的.为了和先前的版本向后兼容,头4个字符(“test”)忽略大小写.(参看http://nunit.org/test.html)
这个测试方法可以定义为:
public void MethodName()
从上面可以看出,这个方法没有任何参数,其实测试方法必须没有参数.如果我们定义方法不对的话,这个方法不会出现在测试方法列表中.也就是说在NUnit的界面左边的工作域内,看不到这个方法.还有一点就是这个方法不返回任何参数,并且必须为Public.
例如:
1using System;
2using NUnit.Framework;
3
4namespace MyTest.Tests
5{
6 [TestFixture]
7 public class SuccessTests
8 {
9 [Test] public void Test1()
10 { /**//* */ }
11 }
12}
13
14
一般来说,有了上面两个属性,你可以做基本的事情了.
另外,我们再对如何进行比较做一个描述。
在NUnit中,用Assert(断言)进行比较,Assert是一个类,它包括以下方法:AreEqual,AreSame,Equals, Fail,Ignore,IsFalse,IsNotNull,具体请参看NUnit的文档。
本文作者:www.LiTianPing.com 来源:http://www.cnblogs.com/ltp/archive/2005/12/03/2897
CIO之家 www.ciozj.com 微信公众号:imciow