.NET中的单元测试(Nunit)入门(一)

1.基础概念

    1.1单元测试

      单元测试:针对程序的某个单元模块进行的测试 (某个方法、某个类型、某个逻辑单元、某个逻辑块)

          notes:  

                 (1). 单元测试在单元模块完成后进行,而测试用例却往往在单元模块完成之前就被确定下来

                 (2). TDD(测试驱动开发): 需求确定下来之后,开始编写测试用例。后续的编辑工作逐渐使得测试

                                        用例全部通过后,开发工作随即完成,单元测试也随之结束,模块可立即交付。

      单元测试优点:

                 1. 验证模块功能:每一项功能靠测试保证其正确性

                 2. 优化了系统设计:程序易于调试和可测试,解除了软件中的耦合

                 3. 另一种文档方式:展示函数/类如何使用的最佳文档

                 4. 具有回归性:编写完成可快速测试

 

2.TDD开发方式的流程

   2.1测试驱动开发的基本过程

       (1).明确当前要完成的功能,可以记录成一个功能列表

       (2).快速编写针对此功能的测试用例

       (3).测试代码编译不通过

       (4).编写对应的功能代码

       (5).测试通过

       (6).对代码进行重构,并保证测试通过

       (7).循环完成所有功能的开发

     

   2.2 TDD的具体实例

          需求:接受一字符串,并且对其进行翻转(可利用StringReverse类型实现此功能)

          设计:定义一个名为StringHandler的类型代表此动作,其包含一个字符串内部成员和公开一个公共方法

                  Reverse实现翻转,该方法返回一个字符串类型的对象来存储翻转的结果。

          测试用例:

//一个测试方法

[Test]

public void TestStringRevertNormal()

{

    String input="abcde";

    StringHandler handler=new StringHandler(input);

    String result=handler.Reverse();

    //测试两个变量是否相等

    Assert.AreEqual("edcba",result);

     Assert.AreEqual("edcba",result);

}

        

          分析: 上面的用例测试了类型的常规功能:翻转字符串。

                     测试用例连续两次调用了同一个测试方法,目的是确保重复调用方法不会影响到同一个模块的功能。

      写完了正常流程的测试用例,就需要做边界测试了。

             1).当传入的参数是null时, 期望该类型抛出一个ArgumentException类型的异常:

/// <summary>

/// 空引用测试用例,希望抛出一个ArgumentException异常

/// </summary>

[Test, ExpectedException(typeof(ArgumentException))]

public void TestStringRevertNullArgument()

{

   String input=null;

   //希望在构造方法中就抛出异常

   StringHandler handler=new StringHandler(input);

}

         2).当传入的参数是空字符时,期望的结果也是返回一个空字符串

///<summary>

///空字符串测试用例

///</summary>

[Test]

public void TestStringRevertEmptyArgument()

{

  String input = String.Empty;

  StringHandler handler=new StringHandler(input);

  String result=handler.Reverse();

  Assert.AreEqual(String.Empty,result);

}

      

       这样就大致已经写完了覆盖所有功能和边界的测试用例了,接下来就可以编写程序的架构来使得所有这些用例能够进行编译。 这里只编写架构,而不进行任何功能实现的编码。

 

///<summary>

///类型的框架,不包含具体功能的实现

///</summary>

class StringHandler

{

    public StringHandler(String input)

    {

        //需要被填充

    }

    public String Reverse()

    {

        //需要被修改

        return String.Enpty;

    }

}

你可能感兴趣的:(.net)