为祖国软件测试事业添砖加瓦!

NUnit 快速入门

上一篇 / 下一篇  2007-07-25 22:14:54 / 个人分类:资料

51Testing软件测试网%f9c|g L]

让我们从一个简单的实例开始吧。假设我们正在编写一个空应用程序,并且我们有一个基本的领域类-Account。Account提供了储蓄,取款,以及转帐等操作。Account类可能如下:51Testing软件测试网G [vW3C:fT q

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;}
    }
  }
}
51Testing软件测试网L-Lj"S^

现在让我们为此类编写第一个测试-AccountTest。我们即将测试的第一个方法是TransferFunds。

sn%`f(i*ws8?*[K0
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);
	
    }
  }
}
51Testing软件测试网:Q;_d~/E

我们注意到的第一件事情就是此类包含一个[TestFixture]属性与之关联-这是一种描述类包含测试代码的方法(此属性可以被继承)。此类必须为public,并且对于其超类没有任何限制。此类也必须有个一缺省的构造子。51Testing软件测试网[-Yh}M%Lw1MIA

51Testing软件测试网a(}8y,O[N

此类包含一个唯一的方法-TransferFunds,而且有一个[Test]属性与之关联-它标志了该方法是一个测试方法。测试方法必须返回void,并且不能带有参数。在我们的测试方法中,我们对一个需要测试的对象进行了普通的初始化,执行以测试的业务方法,并且检查了业务对象的状态。Assert类定义了一组方法,这些方法用来检查前置条件,在我们的例子里,我们使用AreEqual方法保证在转帐之后,2个帐户都有正确的余额(本方法有许多重载方法,在本示例中的版本有如下参数:第一个参数是一个期望值,第二个参数是实际值)。

+OW Rp.`"n C|051Testing软件测试网O j:l0Qzd

编译并运行此实例。假设你已经将你的测试代码编译为一个bank.dll。启动NUnit GUI(安装文件会在桌面和“Program Files"上创建一个快捷方式)。在GUI启动之后,选择File->Open菜单,并指向bank.dll所在的路径,在”Open“对话框打开选择该文件。当bank.dll文件加载之后,你 会在左边的面板上看到一个测试树形结构 ,在右边会有一组状态。点击Run按钮,状态条以及测试树的TransferFunds节点会变红-我们的测试失败了。”Error and Failures"面板显示如下信息:

TransferFunds : expected <250> but was <150>

s9d%}/gv'NL&}0而且,栈跟踪面板会报告测试代码中的失败之处:

D }}|hv0
at bank.AccountTest.TransferFunds() in C:\nunit\BankSampleTests\AccountTest.cs:line 17

'{J+s"DFiR.T ~0这正是我们期望的:测试失败是因为我们并没有实现TransferFunds方法。现在我们让它工作吧。不要关闭此GUI,返回你的IDE并修复此代码,让你的TransferFunds方法如下:

,tv9E `X0
public void TransferFunds(Account destination, float amount)
{
	destination.Deposit(amount);
	Withdraw(amount);
}
51Testing软件测试网1eN}fe)Y

现在,重新编译代码,再一次点击GUI上的按钮-状态条以及测试树变绿了。(注意GUI是如何为您重新加载程序集的;我们会一直打开GUI,并在IDE中继续编写代码,写出更多的测试)。

P ETxY{5b051Testing软件测试网X ei k n$B

让我们在Account代码里加入一些错误的检查。我们为帐户加入最小的余额,保证银行可以继续让他们的钱可以支付最小额度的透支。在Account类里增加一个最小余额的属性:51Testing软件测试网8iM\7L8I

private float minimumBalance = 10.00F;
public float MinimumBalance
{
	get{ return minimumBalance;}
}
51Testing软件测试网K$kCv@W/@

我们使用一个异常来描绘一个透支:

O,w*eThr,P E(H7A0
namespace bank
{
  using System;
  public class InsufficientFundsException : ApplicationException
  {
  }
}
51Testing软件测试网u,ou-R`+G3kb&o M3r

在AccountTest类里加入一个新的方法:51Testing软件测试网*UMD ZB-q7T

[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);
}
51Testing软件测试网E%Q+myj

本测试处理[Test]属性,还有一个[ExpectedException ]属性与之关联-这是一种用来描述测试代码期望某种特定异常的方式。如果这种异常在执行的过程中没有抛出-测试就失败。编译你的代码并返回到GUI。在你编译测试代码的同时,GUI变灰,并且收紧测试树,因为测试还没有运行(当测试树结构改变时,GUI会观察测试的程序集的改变,并更新它自己-例如,加入新的测试等)。点击“Run”按钮-我们又有一个红色的状态条。我们会得到如下失败:

TransferWithInsufficentFunds : InsufficientFundsException was expected
51Testing软件测试网*~ _7pNVab

让我们再一次修复Account代码,按如下方法修改TransferFunds:51Testing软件测试网 SE y0JE!I~u

public void TransferFunds(Account destination, float amount)
{
	destination.Deposit(amount);
	if(balance-amount<minimumBalance)
		throw new InsufficientFundsException();
	Withdraw(amount);
}
51Testing软件测试网.@ZN_H| o

编译并运行测试-绿色的状态条。成功了!但是等等,看看我们刚才编写的代码,我们会发现银行可能在每个没有成功的转帐操作失去一笔钱。让我们编写一个测试来证明我们的疑虑,增加如下测试方法:

)nA4U4U$O"bXs0
[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);
}
51Testing软件测试网_f L d;RPl+C

我们正测试业务方法的事务属性-要么都成功,要么都失败。编译并运行-红条。OK,我们已经让$300.00蒸发了((1999.com déjà vu?)-源帐户有一个正确余额150.00,但是目标帐户则是$450.00.我们如何修复?我们仅需要将最小余额检查调用放在更新的前面即可:

O$}Nn M9|)K0
public void TransferFunds(Account destination, float amount)
{
	if(balance-amount<minimumBalance) 
		throw new InsufficientFundsException();
	destination.Deposit(amount);
	Withdraw(amount);
}
51Testing软件测试网0G O/}#z,^C+Cq

如果Withdraw()方法抛出另外一个异常怎么办?我们应该在捕获代码段中执行一个追加的业务,或是依赖我们的事务管理器来恢复对象的状态?关于这点,我们需要回答一些问题,但不是现在。同时,我们应该对失败的测试最些什么呢?删除它?一个比较好的方式是暂时忽略它,在测试代码中加入如下属性:51Testing软件测试网Z rF,wa nh

[Test]
[Ignore("Decide how to implement transaction management")]
public void TransferWithInsufficientFundsAtomicity()
{
	// code is the same
}

9ok;_9C3ZkH0编译并运行-黄色的状态条。点击“Tests Not Run”,在列表里你会看到e bank.AccountTest.TransferWithInsufficientFundsAtomicity() ,而且带有测试忽略的原因:51Testing软件测试网k5inFstx/i7R G

51Testing软件测试网cQ!R-^I J `1I9C

看一下我们的测试代码,我们会发现某些重构是有顺序的。所有测试方法都共享一组通用的测试对象。我们将这个初始化代码提取到一个setup方法里,并在所有测试中重用它。我们测试类的重构版本如下:

3^ n V)GG.E0W`&X:N0

RV'sk'zn9h0 51Testing软件测试网?h N#l.K%~a&H^

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("Decide how to implement transaction management")]
    public void TransferWithInsufficientFundsAtomicity()
    {
      try
      {
        source.TransferFunds(destination, 300.00F);
      }
      catch(InsufficientFundsException expected)
      {
      }

      Assert.AreEqual(200.00F,source.Balance);
      Assert.AreEqual(150.00F,destination.Balance);
    }
  }
}

HL{o'ob0尽管Init方法有一个通用的初始化代码,但是它返回一个void类型,没有参数。它标记为[SetUp]属性。编译并运行-同样是黄色的状态条。51Testing软件测试网0dCtPF


TAG: Nunit 资料

 

评分:0

我来说两句

我的栏目

日历

« 2024-04-17  
 123456
78910111213
14151617181920
21222324252627
282930    

数据统计

  • 访问量: 12788
  • 日志数: 19
  • 建立时间: 2007-07-18
  • 更新时间: 2011-08-09

RSS订阅

Open Toolbar