NUnit快速入门
时间:2009-6-2 10:09:58 作者: 来源:
 

[译者序]
    纵观软件的开发,测试已经日益成为软件开发过程中的重要环节,通常一个软件的开发周期中测试要占到一半时间甚至更多。而在测试过程中,单元测试更是万里长征第一步,单元测试进行得是否完善,直接影响到后期集成测试的效率。进行单元测试,有许多软件可以自动完成,nunit就是其中之一。这是一款与junit齐名的,同属于xunit家族的单元测试软件(在http://www.nunit.org我们可以免费得到这款软件)。

[正文]

    让我们从一个简单的例子开始。假设我们正在编写一个银行应用程序,而我们有一个这一领域的基本类——account。account支持存款、取款和资金转帐。这个account类看起来会是这个样子:

namespace bank {
public class account {
private float balance;
public void deposit(float amount) {
balance += amount;
}
public void withdraw(float amount) {
balance -= amount;
}
public void transferfunds(account destination, float amount) {
}
public float balance {
get {
return balance;
}
}
}
}
现在我们来为这个类写一个测试——accounttest。我们要测试的第一个类方法是transferfunds。

namespace bank {
using nunit.framework;
[testfixture]
public class accounttest {
[test]
public void transferfunds() {
account source = new account();
source.deposit(200.00f);
account destination = new account();
destination.deposit(150.00f);
source.transferfunds(destination, 100.00f);
assert.areequal(250.00f, destination.balance);
assert.areequal(100.00f, source.balance);
}
}
}
首先要注意的是这个类关联了一个[testfixture]特性(attribute)——这表示这个类包含了测试代码(这个特性可以被继承)。这个类必须是公有的,但他的父类并不受限制。这个类还必须有一个默认构造函数。

    类中唯一的一个方法——transferfunds(),关联了一个[test]特性——这表示它是一个测试方法。测试方法的返回值必须为void并且不能带有参数。在我们的测试方法中,我们对被测试的对象进行了一般的初始化,执行了被测试的方法并检查了对象的状态。assert类定义了一组方法用于检查给定的条件,在我们的例子中我们使用了areequal()方法来确保交易过后两个账户都有正确的余额(这个方法有很多重载,我们在这个例子中使用的版本带有两个参数:第一个参数是我们的期望值,第二个参数是实际值)。

    编译并运行这个例子。假设你已经将你的测试代码编译为bank.dll。打开nuint gui(安装程序会在你的桌面和“程序”菜单中建立一个快捷方式),打开gui后,选择file->open菜单项,找到你的bank.dll并在“open”对话框中选中它。bank.dll装载后你会在左边的面板中看到一个测试树结构,还有右边的一组状态面板。单击run按钮,状态条和测试树种的transferfunds节点变成了红色——我们的测试失败了。“errors and failures”面板显示如下消息——“transferfunds: expected <250> but was <150>”,在它正下方的堆栈跟踪面板报告了测试失败的语句在代码中的位置——“at bank.accounttest.transferfunds() in c:\nunit\banksampletests\accounttest.cs:line 17”

    这正是预期的结果,因为我们还未实现transferfunds()方法。现在我们来搞定它。不要关闭gui,回到你的ide并修改代码,使你的transferfunds()方法看起来像这样:

public void transferfunds(account destination, float amount) {
destination.deposit(amount);
withdraw(amount);
}
现在重新编译你的代码并再次在gui中点击run按钮——状态条和数节点变绿了。(注意gui会自动地为你重新加载程序集;我们可以一直开着gui而在ide中继续工作并写更多的测试)。

    让我们来为我们的account的代码添加一些错误检测。为账户添加一个最小余额限制,通过你的最小透支保护费来维持它的持续运作。首先我们来为account类添加一个最小余额保护属性:

private float minimumbalance = 10.00f;
public float minimumbalance {
get {
return minimumbalance;
}
}
我们使用一个异常来指出透支:

namespace bank {
using system;
public class insufficientfundsexception : applicationexception {
}
}
向我们的accounttest类添加一个新的方法:

[test]
[expectedexception(typeof(insufficientfundsexception))]
public void transferwithinsufficientfunds() {
account source = new account();
source.deposit(200.00f);
account destination = new account();
destination.deposit(150.00f);
source.transferfunds(destination, 300.00f);
}
这个测试方法除了[test]特性之外还关联了一个[expectedexception]特性——这指出测试代码希望抛出一个指定类型的异常;如果在执行过程中没有抛出这样的一个异常——该测试将会失败。编译你的代码并回到gui。由于你编译了你的测试代码,gui会变灰并重构了测试树,好像这个测试还没有被运行过(gui可以监视测试程序集的变化,并在测试树结构发生变化时进行更新——例如,添加了新的测试)。点击“run”按钮——我们又一次得到了一个红色的状态条。我们得到了下面的失败消息:“

[1] [2] [3] 下一页

transferwithinsufficentfunds: insufficientfundsexception was expected”。我们来再次修改account的代码,象下面这样修改transferfunds()方法:

public void transferfunds(account destination, float amount) {
destination.deposit(amount);
if(balance - amount < minimumbalance)
throw new insufficientfundsexception();
withdraw(amount);
}
编译并运行测试——绿了。成功!不过等等,看看我们刚写的代码,我们会发现银行在每一笔不成功的转账操作时都亏钱了。让我们来写一个测试来确认我们的猜测。添加这个测试方法:

[test]
public void transferwithinsufficientfundsatomicity() {
account source = new account();
source.deposit(200.00f);
account destination = new account();
destination.deposit(150.00f);
try {
source.transferfunds(destination, 300.00f);
}
catch(insufficientfundsexception expected) {
}
assert.areequal(200.00f,source.balance);
assert.areequal(150.00f,destination.balance);
}
我们测试了方法的交易属性——是否所有的操作都成功了。编译并运行——红条。是的,我们平白无故地损失了300块钱——source账户有正确的余额150.00,但destination账户显示:$450.00。我们该如何修改?我们能够只将最小余额检查的调用放到数据更新的前面么:

public void transferfunds(account destination, float amount) {
if(balance - amount < minimumbalance) {
throw new insufficientfundsexception();
}
destination.deposit(amount);
withdraw(amount);
}
如果withdraw()方法抛出了另外一个异常呢?我们应该在catch块中执行一个补救处理,还是依赖我们的交易管理器来重新装载对象的状态?某些时候我们必须回答这样的问题,但不是现在;可我们眼前如何应付这个失败的测试呢——删除它?一个不错的方法是临时忽略它在你的测试方法中添加下面的特性:

[test]
[ignore("need to decide how to implement transaction management in the application")]
public void transferwithinsufficientfundsatomicity() {
// code is the same
}
编译并运行——黄条。单击“test not run”选项卡,你会看到bank.accounttest.transferwithinsufficientfundsatomicity()连同这个测试被忽略的原因一起列在列表中。

    看看我们的测试代码,我们可以看到一些适宜的重构。

上一页  [1] [2] [3] 下一页

所有的方法共享一组公共的测试对象。让我们来将这些初始化代码放到一个setup方法中并在所有的测试中重用它们。我们的测试类的重构版本像下面这样:

namespace bank {
using system;
using nunit.framework;
[testfixture]
public class accounttest {
account source;
account destination;
[setup]
public void init() {
source = new account();
source.deposit(200.00f);
destination = new account();
destination.deposit(150.00f);
}
[test]
public void transferfunds() {
source.transferfunds(destination, 100.00f);
assert.areequal(250.00f, destination.balance);
assert.areequal(100.00f, source.balance);
}
[test]
[expectedexception(typeof(insufficientfundsexception))]
public void transferwithinsufficientfunds() {
source.transferfunds(destination, 300.00f);
}
[test,
ignore (
"need to decide how to implement transaction management in the application"
)]
public void transferwithinsufficientfundsatomicity() {
try {
source.transferfunds(destination, 300.00f);
}
catch(insufficientfundsexception expected) {
}
assert.areequal(200.00f,source.balance);
assert.areequal(150.00f,destination.balance);
}
}
}
注意这个初始化方法拥有通用的初始化代码,它的返回值类型为void,没有参数,并且由[setup]特性标记。编译并运行——同样的黄条!

上一页  [1] [2] [3] 

上一篇:
下一篇:
 
网页模板 网站模板 网站建设 网页设计 网页设计师兼职 自助建站 ...
网站魔坊,网页模板,网站模板,免费网页模板,在线模板设计,免费建站,门户网站搭建,建站,企业网站,奇思网络,奇思,智能建站,自助建站,拖动建站,网站建设,网页设计,在线设计模板
www.wzmof.com/ 47K 2009-5-21
 
商巢...
商巢是一个真实的商业交友社区、为用户提供交友、贸易、社区、建站等服务;临渊慕鱼,不如退而结网!商巢结网行动
www.ncooo.com/ 47K 2009-5-21
 
商巢创业 门户创业 商人网络家园 魔坊建站 商业交友
商巢下的门户,门户又一独立实体与商巢合作,由商巢负责技术的更新以及硬件的支持,门户负责自己领域的市场推广以及相应的售后服务即可。 打破以往门户需要源源不断的技术、硬件投入模式,盈利模式清晰 行业门户以及门户下企业网站由网站魔坊...
mhcy.ncooo.com/ 36K 2009-5-14
 
奇思网络技术 网站建设 深圳网站建设
中小外贸企业做电子商务,需要从两点技术突围 08-01 企业网站建设 提供网站策划、网站建设、数据库开发至网络营销全套解决方案。能针对客户所处行业,结合营销特征量身订做高质量网站建设方案。 网站推广 怎样使网站的投资得到回报?这需要经验...
www.qsnet.com.cn/ 48K 2009-4-2
 
深圳艺术网
深圳艺术网,中国艺术网,中国当代艺术网,广东当代艺术网,广东艺术网,南方当代艺术网,深圳美术网,深港美术网,深港艺术网,深港当代艺术网,杜应红,深圳当代艺术创作库,深圳创库,深圳美术,深圳艺术,深圳收藏,深圳艺术收藏,深圳音乐网,深圳舞蹈...
www.szarts.cn/ 119K 2009-6-9
 
网页设计也通过人脉赚钱-技术传播
 
网页设计114 -打造中国网页设计、网站建设技术信息学习、交流、互动平台
                         打造网页设计师兼职创业平台中心