NUnit单元测试笔记Ⅱ基础篇

使用NUnit编写测试

构建单元测试                                                

如果你有一个名为CreateAccount 的被测试函数,俺么你的第一个测试函数的名称也许就是CreateSimpleAccount等等。它会以恰当的参数调用CreateAccount并验证CreateAccount的行为是否和它宣称的一样。当然你也可以有许多测试方法来执行CreateAccount(毕竟,不是所有account都是简单) 。

 

<截图来自<单元测试之道>>

  

测试代码仅限于我们内部使用。客户或者最终用户永远都不会看到,更不会使用这些代码。因此,你懂的。

测试代码必须要做一下这几件事情:

  ● 准备测试所需要的各种条件(创建所有必须的对象,分配必要资源等等)

  ● 调用要测试的方法

  ● 验证被测试方法的行为和期望是否一致。

  ● 完成后清理各种资源。

NUnit各种断言                                                  

  断言是单元测试最基本的组成部分。因此,NUnit程序库以Assert类的静态方法的形式提供了不同形式的多种断言。

 

  ■ AreEqual

  Assert.AreEqual(expexted, actual[,string message])

  这是使用的最多的断言形式,在上面的参数中,expected是你的期望值(通常是硬编码的),actual是被测试代码实际产生的值,message是一个可选的消息,如果提供的话,就爱你工会在发生错误的时候报告这个消息。

  计算机并不能精确的表示所有的浮点数,通常会有一下偏差。因此,如果你想用断言来比较浮点数(float或者是double)则需要指定一个额外的误差参数。它表明你需要多接近才能认为两数“相等”。

 

  ■ IsNull

  Assert.IsNull(object [ , string message])

  Assert.IsNotNull(object [ , string message])

  验证一个给定的对象是否为null,如果答案为否,则将会失败。Message参数是可选的。

 

  ■ AreSame

  Assert.AreSame(expected, actual [ , string message])

  验证expected参数和actual参数所引用的是否为同一个对象,如果不是的话,将会失败。Message参数是可选的。

 

  ■ IsTrue

  Assert.IsTrue(bool condition , actual [ , string message])

  验证给定的二元条件是否为真,如果假的话,将会失败。Message参数是可选的

 

  ■ Fail

  Assert.Fail([string messge])

  上面的断言将会使测试立即失败,其中message参数是可选的。这种断言通常被用于标记某个不应该被到达的分支,但它在实际中并不常用。

NUnit框架                                                     

  下面是一段简单的测试代码,它展示了开始使用该框架的最小要求:

    
    using NUnit.Framework;
    [TestFixture]
    public class TestLargest
    {
        [Test]
        public void LargestOf3()
        {
            Assert.AreEqual(-7, Cmp.Largest(new int[] { -9, -8, -7 }));
        }
    }

 

  首先,第一行的using声明引入了必须的NUnit类。NUnit框架提供了我们需要的单元测试的功能,包括所有我们在前面描述的断言方法。

  接下来,我们看到【TestFixture】特性标记。而且这个类必须声明为public,而且它必须有一个public的、没有参数的构造函数(默认构造函数就行了)。

  最后,测试类包含了用【Test】特性标记的方法。所有用【Test】标记的public方法都会被NUnit自动运行。

NUnit测试的组成                                                  

  如我们刚才看到的一个【TestFixture】标记的类包含一个或多个测试方法:每个方法包含一个或多个断言。一个程序集可以包含多个testFixture。

  我们可以把现存的多个testFixture 组合进一个testSuite中,一个testSuite是一些testFixture类的集合。用【Suite】特性标记。

  Suite是层次化组织测试的一个很有用的机制。特别是对于无人照料的构建,用它来调整测试集合是非常方便的。

  ■ Categories

  NUnit提供了另一种机制Categories,你可以用它来对每个单独的测试方法和testFixtur分门别类。一个category是指你定义的一个名字。你可以把不同的测试方法关联到一个或多个category,然后在运行测试的时候,选择你想要运行的category。

  比如,你可以使用category来把运行时间较短的测试和运行时间较长的测试分开。显然,前一种测试将经常被运行,后一种则可能只是在夜晚构建的时候才运行一次。

  Category是以attribute特性的形式来指定的。当声明方法的时候,你可以提供一个祖父来指定它的category。然后,在你运行测试的时候,可以指定你要运行那些category(你可以一次执行运行多个category)。

namespace UnitTest
{
    [TestFixture]
    public class TestLargest
    {
        [Test]
        [Category("Short")]
        public void LargestOf3()
        {
            Assert.AreEqual(-7, Cmp.Largest(new int[] { /*......*/}));
        }
        [Test,Category("Short")]
        public void LargestOf30()
        { 
            Assert.AreEqual(77,Cmp.Largest(new int[]{ /*......*/ }));
        }
        [Test]
        [Category("Long")]
        public void LargestOf3000()
        {
            Assert.AreEqual(77, Cmp.Largest(new int[] { /*......*/ }));
        }
    }
}


  你可以分开2行指定多个特性(test和category),也可以写在1行。

  打开NUnit,我们可以看到category选项卡中有short和long,你只需选中要执行的,添加到下面的list里,再excute一下就ok了。

  

 

  ■ Per-method的Setup和Teardown

每个测试的运行都应该是相互独立的;从而你就可以在任何时候,以任意的顺序运行每个单独的测试。

为了获得这样的好处,在每个测试开始之前,你都需要重新设置某些测试环境,或者在测试完成之后,你需要释放一些资源。借助于一些Attribute,NUnit让你指定2种方法,分别用于环境的建立和清理:

 [SetUp]
 public void MySetup()
 {/* ..... */ }
 [TearDown]
 public void MyTeardown()
 {/* ..... */ }

  在这个例子中,在调用每个【Test】方法之前,调用方法MySetup;并且在每个测试方法完成之后,调用方法MyTeardown()。

  比如,如果对于每个测试你都需要某种数据库连接。这时,你就不需要在每个测试方法中重复建立连接和释放连接了,而只须在SetUp和TearDown方法中分别建立和释放连接:

    [TestFixture]
    public class TestDB

    {

        private Connection dbConn;

        [SetUp]
        public void MySetup()
        {
            dbConn = new Connection("oracle", 1521, "user", "psw");
            dbConn.Connect();
        }

        [TearDown]
        public void MyTeardown()
        {
            dbConn.Disconnect();
            dbConn = null;
        }

        [Test]
        public void TestAccountAccess()
        { }

        [Test]
        public void TestEmployeeAccess()
        { }
    }


  ■ Per-class的Setup和Per-class的Teardown

  知道了Per-method,那就容易理解Per-class了。

    

    [TestFixtureSetUp]
    public class OneTimeSutup
    {}
    [TestFixtureTearDown]
    public class OneTimeTeardown
    { }

  结合刚才的两个就是

 

 

原文地址:https://www.cnblogs.com/TivonStone/p/1839583.html