一 NUnit是一款堪与JUnit齐名的开源的回归测试框架,供.net开发人员做单元测试之用,可以从
		
				www.nunit.org
		
		网站上免费获得,我下的是 
..
二 安装NUnit(很简单的,直接next就可以拉)
三 新建console的c#的.net2005的project.里面包含要被测试的和测试程序. 记的要ref  unuit.framework .dll ,还有using NUnit.Framework; 并build产成.exe.
 
 using System;
using System;
 using System.Collections.Generic;
using System.Collections.Generic;
 using System.Text;
using System.Text;
 using NUnit.Framework;
using NUnit.Framework;
 namespace Nunit
namespace Nunit


 {
{
 class Program
    class Program

 
     {
{
 static void Main(string[] args)
        static void Main(string[] args)

 
         {
{
 }
        }
 }
    }

 }
}
 namespace NUnitCS
namespace NUnitCS


 {
{

 /**//// <summary>
    /**//// <summary>
 /// Book 的摘要说明。
    /// Book 的摘要说明。
 /// </summary>
    /// </summary>
 public class Book
    public class Book

 
     {
{
 private string pid = null;
        private string pid = null;
 private string pname = null;
        private string pname = null;

 public string id
        public string id

 
         {
{
 get
            get

 
             {
{
 return pid;
                return pid;
 }
            }
 set
            set

 
             {
{
 pid = value;
                pid = value;
 }
            }
 }
        }

 public string name
        public string name

 
         {
{
 get
            get

 
             {
{
 return pname;
                return pname;
 }
            }
 set
            set

 
             {
{
 pname = value;
                pname = value;
 }
            }
 }
        }
 }
    }
 }
}
 namespace NUnitCS
namespace NUnitCS


 {
{

 /**//// <summary>
    /**//// <summary>
 /// BookTest 的摘要说明。
    /// BookTest 的摘要说明。
 /// </summary>
    /// </summary>
 [TestFixture]
    [TestFixture]
 public class BookTest
    public class BookTest

 
     {
{
 Book book = null;
        Book book = null;

 [TestFixtureSetUp]
        [TestFixtureSetUp]
 public void Init()
        public void Init()

 
         {
{
 Console.WriteLine("测试开始!");
            Console.WriteLine("测试开始!");
 book = new Book();
            book = new Book();
 Console.WriteLine("book对象被初始化!");
            Console.WriteLine("book对象被初始化!");
 }
        }

 [Test]
        [Test]
 public void testId()
        public void testId()

 
         {
{
 book.id = "001"; //设置id属性的值为001
            book.id = "001"; //设置id属性的值为001
 //使用Assert查看id属性的值是否为001
            //使用Assert查看id属性的值是否为001
 Assert.AreEqual("001", book.id);
            Assert.AreEqual("001", book.id);
 Console.WriteLine("id属性被测试!");
            Console.WriteLine("id属性被测试!");
 }
        }

 [Test]
        [Test]
 public void testName()
        public void testName()

 
         {
{
 book.name = "ASP"; //设置name属性的值为ASP
            book.name = "ASP"; //设置name属性的值为ASP
 //使用Assert查看name属性的值是否为JSP,这是个必然出现错误的测试
            //使用Assert查看name属性的值是否为JSP,这是个必然出现错误的测试
 Assert.AreEqual("JSP", book.name);
            Assert.AreEqual("JSP", book.name);
 Console.WriteLine("name属性被测试!");
            Console.WriteLine("name属性被测试!");
 }
        }

 [TestFixtureTearDown]
        [TestFixtureTearDown]
 public void Dispose()
        public void Dispose()

 
         {
{
 Console.WriteLine("book对象将被清理!");
            Console.WriteLine("book对象将被清理!");
 book = null;
            book = null;
 Console.WriteLine("测试结束!");
            Console.WriteLine("测试结束!");
 }
        }
 }
    }
 }
}


四 测试用例
这里只用了一个类进行测试,名为BookTest,以前这样的类可能需要继承NUnit.Framework.TestCase类,但现在只需要对该类使用TestFixture属性进行标识即可,而无须继承了。BookTest类包含两个用例,分别对应该类的testId和testName方法,即每个方法实现了一个测试用例。注意,在NUnit中,这些用来实现测试用例的方法有两种手段进行标识:一个是以testXXX的格式来命名,一个是使用Test属性进行标识。此外,BookTest还有Init和Dispose这两个方法,并分别使用TestFixtureSetUp和TestFixtureTearDown属性来进行标识,前者在每个测试方法开始之前执行,多用来做初始化;后者在每个测试方法完成之后执行,多用来清理资源。注意,这两个方法的名称并没有什么限制,但必须用TestFixtureSetUp和TestFixtureTearDown属性进行标识。下面开始编写BookTest。上例中的测试用例booktest中,
这里Init和Dispose方法没什么好说的,就是执行了对book对象的初始化和清理,不过testId和testName需要说明一下。前者是在对bo的id属性进行测试,首先赋值为”001”,然后使用Assert的AreEqual方法查看id属性中存放的值是否是期待的值,由于我的期待值也是”001”,所以执行后这个用例应该是成功的;后者则是对bo的name属性进行测试,也是首先赋值为”ASP”,然后使用Assert的AreEqual方法查看其值是否是期待的,由于我特意将期待值设定为根本不可能的”JSP”,因此这个用例执行后会出现一个错误。但请注意,由于我是特意要让测试出现错误,所以将期待值设定成了不可能的值,如果你是测试人员,请千万不要这么做,否则如果别的地方导致了错误,很容易给自己造成不必要的麻烦。
  下面简单介绍一下上边用到的静态类NUnit.Framework.Assert。该类主要包含6个方法:
  1.AreEqual()方法,用来查看对象中存的值是否是期待的值,与字符串比较中使用的Equals()方法类似;
  2.IsFalse()和IsTrue()方法,用来查看变量是是否为false或true,如果IsFalse()查看的变量的值是false则测试成功,如果是true则失败,IsTrue()与之相反。
  3.AreSame()方法,用来比较两个对象的引用是否相等,类似于通过“Is”或“==”比较两个对象;
  4.IsNull()和IsNotNull()方法,用来查看对象是否为空和不为空。
五 打开NUnit-Net-2.0 2.2.8.exe工具.file->open.打开上面产生的exe.然后选择你要测试的方法,click thebutton "RUN".
 testId前的点依然是绿色,但testName前的点是红色,而且进度条显示为红条,这表明testName中存在错误。不过这个错误是预计之内的,如果不想看到,可以在vs03中将testName()方法中的”JSP”改成”ASP”,然后重新运行。此时无须重新启动NUnit,NUnit会自动加载重新编写好的文件。此时再运行BookTest,进度条已不是红色,而是绿色了。
testId前的点依然是绿色,但testName前的点是红色,而且进度条显示为红条,这表明testName中存在错误。不过这个错误是预计之内的,如果不想看到,可以在vs03中将testName()方法中的”JSP”改成”ASP”,然后重新运行。此时无须重新启动NUnit,NUnit会自动加载重新编写好的文件。此时再运行BookTest,进度条已不是红色,而是绿色了。
六 unuit.framework 的高级属性
1 但除了TestFixture、TestFixtureSetUp、Test和TestFixtureTearDown这四个常用的属性外,NUnit还提供了ExpectedException、Ignore、Suite、Category和Explicit等属性用于测试。
2、ExpectedException
  ExpectedException属性用于测试是否会抛出指定的异常,若抛出则NUnit的状态条为绿色,反之为红色。
  示例代码:
  using System;
  using NUnit.Framework;    
namespace NUnitTest
  {
    [TestFixture]
    public class Test1
    {
      [Test]
      [ExpectedException(typeof(Exception))]
      public void TestExpectedException()
      {
        string s = "";
        if (s != "")
          throw new Exception();
      }
    }
  }
  测试效果:状态条为红色。
  具体说明:由于字符串s在初始化时已赋值为"",因此在判断"s != """时条件自然不会成立,这样就不会抛出异常,状态条当然也就不会为绿色了。如果想让状态条显示为绿色,将判断条件改为"s == """就可以了。
3、Ignore
  Ignore属性可以供类和方法使用,使用后类或方法在NUnit测试中会被忽略,也就是说,对于暂时不想运行的测试类或测试方法,可以通过Ignore属性将其忽略掉。
  示例代码1:
  [TestFixture]
  [Ignore("class test ignore")]
  public class Test2
  {
    [Test]
    public void TestIgnore()
    {}
  }
  示例代码2:
  [TestFixture]
  public class Test2
  {
    [Test]
    [Ignore("function test ignore")]
    public void TestIgnore()
    {}
  }
  测试效果:两个示例被执行后状态条都会显示为黄色。但如果你在测试时选择的是Test2节点,就会发现示例一执行后,只有Test2节点前的圆点显示为黄色,状态条没有发生任何变化,而示例二则会将Test2和TestIgnore节点前的圆点都变成黄色,状态条也显示成黄色。这是由于前者忽略的是整个类的测试,而后者忽略的只是测试方法。
4、Suite
  根据NUnit文档的说明,Suite属性是用来标记返回类型为NUnit.Core.TestSuite的类属性成员的,该类属性成员所返回的对象会包含一组测试类,也就是说Suite属性其实是用来组织一组测试类的。那么组织这些测试类到TestSuite对象中有何用呢?其实在早期的NUint当中,提供有NUnit.TextUI.TestRunner类,该类有个Run方法,参数就是TestSuite对象,通过该方法可以在代码中调用NUnit环境,从而运行TestSuite对象中的测试类。不过现在NUnit似乎已经不再使用这种方式了,故此对于Suite属性这里不再介绍。
5、Category
  Category属性用于将测试类和测试方法分组,从而使测试类和测试方法可以分组进行测试。
  示例代码1:
  [TestFixture]
  [Category("Class1")]
  public class Test31
  {
    [Test]
    public void Test()
    {}
  }
  
  [TestFixture]
  [Category("Class1")]
  public class Test32
  {
    [Test]
    public void Test()
    {}
  }
  
  [TestFixture]
  [Category("Class2")]
  public class Test33
  {
    [Test]
    public void Test()
    {}
  }
  
  [TestFixture]
  [Category("Class2")]
  public class Test34
  {
    [Test]
    public void Test()
    {}
  }
  示例代码2:
  [TestFixture]
  public class Test3
  {
    [Test]
    [Category("m1")]
    public void Test11()
    {}
    
    [Test]
    [Category("m1")]
    public void Test12()
    {}
    
    [Test]
    [Category("m2")]
    public void Test21()
    {}
    
    [Test]
    [Category("m2")]
    public void Test22()
    {}
  }
  测试效果:示例一中编写了四个类,被分为Class1和Class2两个组;示例二中编写了四个方法,被分成了m1和m2两个组。对于这种分组的测试,要想看出效果,在打开NUnit后,需要先在Categories选项卡中作出选择,如下图所示:
可以看到,所有的组默认都在上边的Available Categories列表框中,选中的组则通过Add按钮添加到下边的Selected Categories列表框中,NUnit允许选中多个。测试完成后对于不想要的组,还可以通过Remove按钮放回到上边。选好后,点击Run按钮,再选择Tests选项卡,效果如下图:
可以看到,只有与Class1编组对应的Test31和Test32这两个类被测试了。
6、Explicit
  Explicit属性与Ignore属性有些类似,也是用于对暂时不想运行的测试类或测试方法做忽略的。但与Ignore属性相比还有两点差别:一个是Explicit属性不需要说明信息,一个是使用Explicit属性做忽略的类或方法在NUnit中被选中后,将不再被忽略,而是进行测试。
  示例代码1:
  [TestFixture]
  public class Test4
  {
    [Test, Explicit]
    public void TestMethod()
    {}
  }
  示例代码2:
  [TestFixture, Explicit]
  public class Test42
  {
    [Test]
    public void TestMethod()
    {}
  }
  测试效果:示例一所忽略的是方法,若不在NUnit中选中该方法,测试后该方法前的圆点为黄色,即在测试中被忽略,若选中了则在测试后显示为绿色或红色,这与测试的结果有关;示例二所忽略的是类,效果与示例一类似。
附:
 using System;
using System;
 using System.Collections.Generic;
using System.Collections.Generic;
 using System.Text;
using System.Text;
 using NUnit.Framework;
using NUnit.Framework;
 namespace Nunit
namespace Nunit


 {
{
 class Program
    class Program

 
     {
{
 static void Main(string[] args)
        static void Main(string[] args)

 
         {
{
 }
        }
 }
    }

 }
}
 namespace NUnitCS
namespace NUnitCS


 {
{

 /**//// <summary>
    /**//// <summary>
 /// Book 的摘要说明。
    /// Book 的摘要说明。
 /// </summary>
    /// </summary>
 public class Book
    public class Book

 
     {
{
 private string pid = null;
        private string pid = null;
 private string pname = null;
        private string pname = null;

 public string id
        public string id

 
         {
{
 get
            get

 
             {
{
 return pid;
                return pid;
 }
            }
 set
            set

 
             {
{
 pid = value;
                pid = value;
 }
            }
 }
        }

 public string name
        public string name

 
         {
{
 get
            get

 
             {
{
 return pname;
                return pname;
 }
            }
 set
            set

 
             {
{
 pname = value;
                pname = value;
 }
            }
 }
        }
 }
    }
 }
}
 namespace NUnitCS
namespace NUnitCS


 {
{

 /**//// <summary>
    /**//// <summary>
 /// BookTest 的摘要说明。
    /// BookTest 的摘要说明。
 /// </summary>
    /// </summary>
 [TestFixture]
    [TestFixture]
 public class BookTest
    public class BookTest

 
     {
{
 Book book = null;
        Book book = null;

 [TestFixtureSetUp]
        [TestFixtureSetUp]
 public void Init()
        public void Init()

 
         {
{
 Console.WriteLine("测试开始!");
            Console.WriteLine("测试开始!");
 book = new Book();
            book = new Book();
 Console.WriteLine("book对象被初始化!");
            Console.WriteLine("book对象被初始化!");
 }
        }

 [Test]
        [Test]
 public void testId()
        public void testId()

 
         {
{
 book.id = "001"; //设置id属性的值为001
            book.id = "001"; //设置id属性的值为001
 //使用Assert查看id属性的值是否为001
            //使用Assert查看id属性的值是否为001
 Assert.AreEqual("001", book.id);
            Assert.AreEqual("001", book.id);
 Console.WriteLine("id属性被测试!");
            Console.WriteLine("id属性被测试!");
 }
        }

 [Test]
        [Test]
 public void testName()
        public void testName()

 
         {
{
 book.name = "ASP"; //设置name属性的值为ASP
            book.name = "ASP"; //设置name属性的值为ASP
 //使用Assert查看name属性的值是否为JSP,这是个必然出现错误的测试
            //使用Assert查看name属性的值是否为JSP,这是个必然出现错误的测试
 Assert.AreEqual("JSP", book.name);
            Assert.AreEqual("JSP", book.name);
 Console.WriteLine("name属性被测试!");
            Console.WriteLine("name属性被测试!");
 }
        }

 [TestFixtureTearDown]
        [TestFixtureTearDown]
 public void Dispose()
        public void Dispose()

 
         {
{
 Console.WriteLine("book对象将被清理!");
            Console.WriteLine("book对象将被清理!");
 book = null;
            book = null;
 Console.WriteLine("测试结束!");
            Console.WriteLine("测试结束!");
 }
        }
 }
    }
 }
}
 namespace NUnitTest
namespace NUnitTest


 {
{
 [TestFixture]
    [TestFixture]
 public class Test1
    public class Test1

 
     {
{
 [Test]
        [Test]
 [ExpectedException(typeof(Exception))]
        [ExpectedException(typeof(Exception))]
 public void TestExpectedException()
        public void TestExpectedException()

 
         {
{
 string s = "";
            string s = "";
 if (s != "")
            if (s != "")
 throw new Exception();
                throw new Exception();
 }
        }
 }
    }
 [TestFixture]
    [TestFixture]
 [Ignore("class test ignore")]
    [Ignore("class test ignore")]
 public class Test21
    public class Test21

 
     {
{
 [Test]
        [Test]
 public void TestIgnore()
        public void TestIgnore()

 
         { }
{ }
 }
    }
 [TestFixture]
    [TestFixture]
 public class Test22
    public class Test22

 
     {
{
 [Test]
        [Test]
 [Ignore("function test ignore")]
        [Ignore("function test ignore")]
 public void TestIgnore()
        public void TestIgnore()

 
         { }
{ }
 }
    }
 [TestFixture]
    [TestFixture]
 [Category("Class31")]
    [Category("Class31")]
 public class Test31
    public class Test31

 
     {
{
 [Test]
        [Test]
 public void Test()
        public void Test()

 
         { }
{ }
 }
    }

 [TestFixture]
    [TestFixture]
 [Category("Class32")]
    [Category("Class32")]
 public class Test32
    public class Test32

 
     {
{
 [Test]
        [Test]
 public void Test()
        public void Test()

 
         { }
{ }
 }
    }

 [TestFixture]
    [TestFixture]
 [Category("Class33")]
    [Category("Class33")]
 public class Test33
    public class Test33

 
     {
{
 [Test]
        [Test]
 public void Test()
        public void Test()

 
         { }
{ }
 }
    }

 [TestFixture]
    [TestFixture]
 [Category("Class34")]
    [Category("Class34")]
 public class Test34
    public class Test34

 
     {
{
 [Test]
        [Test]
 public void Test()
        public void Test()

 
         { }
{ }
 }
    }
 [TestFixture]
    [TestFixture]
 public class Test3
    public class Test3

 
     {
{
 [Test]
        [Test]
 [Category("m1")]
        [Category("m1")]
 public void Test11()
        public void Test11()

 
         { }
{ }

 [Test]
        [Test]
 [Category("m1")]
        [Category("m1")]
 public void Test12()
        public void Test12()

 
         { }
{ }

 [Test]
        [Test]
 [Category("m2")]
        [Category("m2")]
 public void Test21()
        public void Test21()

 
         { }
{ }

 [Test]
        [Test]
 [Category("m2")]
        [Category("m2")]
 public void Test22()
        public void Test22()

 
         { }
{ }
 }
    }
 [TestFixture]
    [TestFixture]
 public class Test4
    public class Test4

 
     {
{
 [Test, Explicit]
        [Test, Explicit]
 public void TestMethod()
        public void TestMethod()

 
         { }
{ }
 }
    }
 [TestFixture, Explicit]
    [TestFixture, Explicit]
 public class Test42
    public class Test42

 
     {
{
 [Test]
        [Test]
 public void TestMethod()
        public void TestMethod()

 
         { }
{ }
 }
    }

 }
}




错误为红色;
                        正确为绿色;
                                                      忽略为黄色;
http://blog.csdn.net/qdzx2008/archive/2006/01/28/589494.aspx
http://blog.csdn.net/qdzx2008/archive/2006/01/28/589497.aspx