51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 6339|回复: 15
打印 上一主题 下一主题

NUnit快速入门

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2005-1-26 14:53:45 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
原著:NUnit v2.1
原文:NUnit文档之QuickStart.doc
翻译:lover_P
--------------------------------------------------------------------------------
[译者序]
    纵观软件的开发,测试已经日益成为软件开发过程中的重要环节,通常一个软件的开发周期中测试要占到一半时间甚至更多。而在测试过程中,单元测试更是万里长征第一步,单元测试进行得是否完善,直接影响到后期集成测试的效率。进行单元测试,有许多软件可以自动完成,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”按钮——我们又一次得到了一个红色的状态条。我们得到了下面的失败消息:“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()连同这个测试被忽略的原因一起列在列表中。

    看看我们的测试代码,我们可以看到一些适宜的重构。所有的方法共享一组公共的测试对象。让我们来将这些初始化代码放到一个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]特性标记。编译并运行——同样的黄条!

============全文完==========

    如果你安装了NUnit V2.1,可以在 开始->程序->NUnit V2.1->QuickStart 处得到原文(英文版)。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏

该用户从未签到

2#
发表于 2005-1-26 15:36:53 | 只看该作者
顶!
回复 支持 反对

使用道具 举报

该用户从未签到

3#
发表于 2005-1-31 14:27:20 | 只看该作者
呵呵,这个是一个很好的工具,顶
回复 支持 反对

使用道具 举报

该用户从未签到

4#
发表于 2005-1-31 15:26:13 | 只看该作者
顶!
回复 支持 反对

使用道具 举报

该用户从未签到

5#
发表于 2005-2-4 17:04:29 | 只看该作者

kuang ding!!!!!!!!!!!!!!!

回复 支持 反对

使用道具 举报

该用户从未签到

6#
发表于 2005-2-6 14:30:02 | 只看该作者
好贴,顶!
回复 支持 反对

使用道具 举报

该用户从未签到

7#
发表于 2005-2-6 15:00:36 | 只看该作者

顶!

回复 支持 反对

使用道具 举报

该用户从未签到

8#
发表于 2005-2-7 08:03:25 | 只看该作者
回复 支持 反对

使用道具 举报

该用户从未签到

9#
发表于 2005-2-10 15:30:58 | 只看该作者
过分了,这是NUNIT自己带的呀
回复 支持 反对

使用道具 举报

该用户从未签到

10#
发表于 2005-5-23 13:12:20 | 只看该作者
翻译出来了,精神可佳啊~~~
回复 支持 反对

使用道具 举报

  • TA的每日心情
    开心
    2016-4-1 13:14
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]测试小兵

    11#
    发表于 2006-4-6 22:32:00 | 只看该作者
    我有本书介绍给大家:
    单元测试之道    C#版   ----使用NUNIT
    [美]Andrew Hunt David Thomas著   陈伟柱 陶文  译
    电子工业出版社
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    12#
    发表于 2006-4-12 11:59:37 | 只看该作者
    谢谢楼主翻译
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    13#
    发表于 2006-4-13 00:28:35 | 只看该作者
    其实怎么使用NUNIT只是对c#开发的代码进行测试的入门点.主要问题还是要怎么去做MOCK,也就是说怎么去做桩和驱动.
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    14#
    发表于 2006-4-19 12:53:04 | 只看该作者
    不错,正想学这个
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    15#
    发表于 2006-6-7 09:17:02 | 只看该作者
    谢谢,给我不少启发,顶!!!!!
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    16#
    发表于 2006-10-31 18:13:15 | 只看该作者
    nunit我也研究过,也会一些,但是目前单元测试大部分公司换使程序员自己测,没有发挥余地
    回复 支持 反对

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-11-15 00:02 , Processed in 0.083385 second(s), 28 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表