Nunit 2.5.5的使用总结
引入必要的命名空间:
using NUnit.Framework;
引用组件:
nunit.framework.dll
1.使用Unit的最佳实践:
a.新建一个名为Test的souce folder, 用于存放测试类源代码。
b.目标类与测试类应该位于同一个包下面,这样测试类就不必导入源代码所在的包,因为他们位于
同一包下面。
c.测试类命名规则:假如目标类是Culculator,那么测试类应该命名为TestCalculator或者是CalculatorTest
2.Xunit的口号:Keep the bar green to keep the code clean.
3.单元测试不是为了证明你是对的,而是为了证明你没有错误。
4.测试用例:(Test Case) 是单元测试的一个很重要的方面。
5.单元测试主要是用来判断程序的执行结果与自己期望的结果是否一致。
6.测试方法需要满足如下原则:
a. public的
b. void的
c. 无方法参数
d. 方法名称必须以test开头
e. 方法前面要加上特性[Test]
f. 测试类的前面要加上[TestFixture]
7.TestCast之间一定要保持完全的独立性,不允许出现在任何的依赖关系。
8.我们不能依赖于测试方法的执行顺序。
9.DRY(Don't Repeat Yourself),当你的测试中有重复代码出现时,可以用SeTup和TearDown两个特性,表示
在每个测试方法执行前,调用什么,每个测试方法执行结束之后调用什么.
private int a;
private int b;
private Calc calc;
[SetUp]
public void init()
{
calc = new Calc();
a = 10;
b = 2;
}
[TearDown]
public void Destroy()
{
}
private Calc calc;
[SetUp]
public void init()
{
calc = new Calc();
a = 10;
b = 2;
}
[TearDown]
public void Destroy()
{
}
10.关于SetUp与TearDown方法的执行顺序:
a. setup
b. testAdd
c. teardown
11.测试之前是什么状态,测试执行完毕后就应该是什么状态,而不应该由于测试执行的原因导致
状态发生了变化。
13.测试类的私有方法时可以采取两种方式:
a.修改方法的访问修饰符,将private修改为default或public(但不推荐使用)
b.使用反射在测试类中调用目标类的私有方法(推荐)。
[Test]
public void TestAdd()
{
try
{
Calc2 calc2 = new Calc2();
Type type = calc2.GetType();
MethodInfo method = type.GetMethod("Add",BindingFlags.NonPublic|BindingFlags.Instance);
object result = method.Invoke(calc2, new object[] { 2, 3 });
Assert.AreEqual(5, result);
}
catch (Exception ex)
{
Assert.Fail();
}
}
{
try
{
Calc2 calc2 = new Calc2();
Type type = calc2.GetType();
MethodInfo method = type.GetMethod("Add",BindingFlags.NonPublic|BindingFlags.Instance);
object result = method.Invoke(calc2, new object[] { 2, 3 });
Assert.AreEqual(5, result);
}
catch (Exception ex)
{
Assert.Fail();
}
}
14.Test Suite(测试套件):可以将多个测试组合到一起,同时执行多个测试。
[TestFixture]
public class AllTests
{
using NUnit.Framework;
using NUnit.Core;
[Suite]
public static TestSuite Suite
{
get
{
TestSuite suite = new TestSuite("All Tests");
suite.Add(new Calc2Test());
suite.Add(new LargestTest());
suite.Add(new StackTest());
return suite;
}
}
}
{
using NUnit.Framework;
using NUnit.Core;
[Suite]
public static TestSuite Suite
{
get
{
TestSuite suite = new TestSuite("All Tests");
suite.Add(new Calc2Test());
suite.Add(new LargestTest());
suite.Add(new StackTest());
return suite;
}
}
}
还有两种更为简单的方法:
其一:
namespace CalcTest
{
using NUnit.Framework;
[TestFixture]
public class AllTests
{
[Suite]
public static IEnumerable Suite
{
get
{
ArrayList suite = new ArrayList();
suite.Add(new Calc2Test());
suite.Add(new LargestTest());
suite.Add(new StackTest());
return suite;
}
}
}
}
{
using NUnit.Framework;
[TestFixture]
public class AllTests
{
[Suite]
public static IEnumerable Suite
{
get
{
ArrayList suite = new ArrayList();
suite.Add(new Calc2Test());
suite.Add(new LargestTest());
suite.Add(new StackTest());
return suite;
}
}
}
}
其二:
namespace CalcTest
{
using NUnit.Framework;
[TestFixture]
public class AllTests
{
[Suite]
public static IEnumerable Suite
{
get
{
ArrayList suite = new ArrayList();
suite.Add(typeof(Calc2Test));
suite.Add(typeof(LargestTest));
suite.Add(typeof(StackTest));
return suite;
}
}
}
}
{
using NUnit.Framework;
[TestFixture]
public class AllTests
{
[Suite]
public static IEnumerable Suite
{
get
{
ArrayList suite = new ArrayList();
suite.Add(typeof(Calc2Test));
suite.Add(typeof(LargestTest));
suite.Add(typeof(StackTest));
return suite;
}
}
}
}
15.在对数据库进行单元测试的时候,为了避免连接的重复建立,可以调用TestFixtureSetUp和TestFixtureTearDown两个特性:
[TestFixtureSetUp]
public void ConnectionSetup()
{
}
[TestFixtureTearDown]
public void ConnectionDestroy()
{
}
{
}
[TestFixtureTearDown]
public void ConnectionDestroy()
{
}
16.当在单元测试中,想不执行某个单元测试方法时,可以用Ignore特性,表示不永远不会被执行:
[Test]
[Ignore("This case is ignored.")]
public void TestSubtract()
{
int actual = calc.Subtract(a, b);
int expect = 8;
Assert.AreEqual(expect, actual);
}
public void TestSubtract()
{
int actual = calc.Subtract(a, b);
int expect = 8;
Assert.AreEqual(expect, actual);
}
17.当在单元测试中,如果不想对某个方法进行单元测试,只是在它被选中时才进行测试的话,可以调用Explicit特性
[Test]
[Explicit]
public void TestMultiple()
{
int actual = calc.Multiple(a, b);
int expect = 20;
Assert.AreEqual(expect, actual);
}
public void TestMultiple()
{
int actual = calc.Multiple(a, b);
int expect = 20;
Assert.AreEqual(expect, actual);
}
18.如果要对测试方法进行分组时,可以用Category特性
[Test]
[Category("GroupA")]
public void TestAdd()
{
int actual = calc.Add(a, b);
int expect = 12;
Assert.AreEqual(expect,actual);
}
[Test]
[Category("GroupA")]
public void TestSubtract()
{
int actual = calc.Subtract(a, b);
int expect = 8;
Assert.AreEqual(expect, actual);
}
[Test]
[Category("GroupB")]
public void TestMultiple()
{
int actual = calc.Multiple(a, b);
int expect = 20;
Assert.AreEqual(expect, actual);
}
[Test]
[Category("GroupB")]
public void TestDevide()
{
int actual = 0;
try
{
actual = calc.Devide(a, b);
}
catch (Exception ex)
{
Assert.Fail();
}
int expect = 5;
Assert.AreEqual(expect, actual);
}
public void TestAdd()
{
int actual = calc.Add(a, b);
int expect = 12;
Assert.AreEqual(expect,actual);
}
[Test]
[Category("GroupA")]
public void TestSubtract()
{
int actual = calc.Subtract(a, b);
int expect = 8;
Assert.AreEqual(expect, actual);
}
[Test]
[Category("GroupB")]
public void TestMultiple()
{
int actual = calc.Multiple(a, b);
int expect = 20;
Assert.AreEqual(expect, actual);
}
[Test]
[Category("GroupB")]
public void TestDevide()
{
int actual = 0;
try
{
actual = calc.Devide(a, b);
}
catch (Exception ex)
{
Assert.Fail();
}
int expect = 5;
Assert.AreEqual(expect, actual);
}
19.一个方法的测试可能要写很多个测试方法,这都是正常的:
一个冒泡排序类:
namespace Calculator
{
public class BubbleSortClass
{
public int[] BubbleSort(int[] array)
{
if (null == array)
{
Console.Error.WriteLine("Prameters shouldn't be null.");
return new int[] { };
}
for (int i = 0; i < array.Length - 1; ++i)
{
bool swap = false;
for (int j = 0; j < array.Length - i - 1; ++j)
{
if (array[j] > array[j + 1])
{
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
swap = true;
}
}
if (!swap)
{
return array;
}
}
return array;
}
}
}
{
public class BubbleSortClass
{
public int[] BubbleSort(int[] array)
{
if (null == array)
{
Console.Error.WriteLine("Prameters shouldn't be null.");
return new int[] { };
}
for (int i = 0; i < array.Length - 1; ++i)
{
bool swap = false;
for (int j = 0; j < array.Length - i - 1; ++j)
{
if (array[j] > array[j + 1])
{
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
swap = true;
}
}
if (!swap)
{
return array;
}
}
return array;
}
}
}
一个测试冒泡排序的类,尽可能的考虑到所有的情况:
namespace CalcTest
{
using NUnit.Framework;
[TestFixture]
public class BubbleSortTest
{
BubbleSortClass bubble;
[SetUp]
public void Init()
{
bubble = new BubbleSortClass();
}
[Test]
public void TestBubbleSort()
{
int[] array = { 1, 4, 8, 4, 9, 5, 7, 4, -10 };
int[] result = bubble.BubbleSort(array);
int[] expect = { -10, 1, 4, 4, 4, 5, 7, 8, 9 };
Assert.AreEqual(expect, result);
}
[Test]
public void TestBubbleSort2()
{
int[] arr = null;
int[] result = bubble.BubbleSort(arr);
int[] expect = { };
Assert.AreEqual(expect, result);
}
[Test]
public void TestBubbleSort3()
{
int[] arr = { };
int[] result = bubble.BubbleSort(arr);
int[] expect = { };
Assert.AreEqual(expect, result);
}
}
}
{
using NUnit.Framework;
[TestFixture]
public class BubbleSortTest
{
BubbleSortClass bubble;
[SetUp]
public void Init()
{
bubble = new BubbleSortClass();
}
[Test]
public void TestBubbleSort()
{
int[] array = { 1, 4, 8, 4, 9, 5, 7, 4, -10 };
int[] result = bubble.BubbleSort(array);
int[] expect = { -10, 1, 4, 4, 4, 5, 7, 8, 9 };
Assert.AreEqual(expect, result);
}
[Test]
public void TestBubbleSort2()
{
int[] arr = null;
int[] result = bubble.BubbleSort(arr);
int[] expect = { };
Assert.AreEqual(expect, result);
}
[Test]
public void TestBubbleSort3()
{
int[] arr = { };
int[] result = bubble.BubbleSort(arr);
int[] expect = { };
Assert.AreEqual(expect, result);
}
}
}
20.如果你期望你的测试方法能抛出异常,可以用ExpectedException特性,它通常用于异常的测试:
[Test]
[ExpectedException(typeof(DivideByZeroException))]
public void TestDevideByZero()
{
int actual = 0;
actual = calc.Devide(2, 0);
}
public void TestDevideByZero()
{
int actual = 0;
actual = calc.Devide(2, 0);
}
21.当你而要对一个测试方法进行多组数据测试时,可以用一个文件将数据保存起来,然后编写程序去读取
,达到多组数据测试的目的,方式比较灵活,可以用xml,txt等格式.
首先写一个要测试的类:
namespace Calculator
{
public class Largest
{
public int GetLargest(int[] array)
{
if (null == array || 0 == array.Length)
{
throw new Exception("数组不能为空!");
}
int result = array[0];
for (int i = 0; i < array.Length; i++)
{
if (result < array[i])
{
result = array[i];
}
}
return result;
}
}
}
{
public class Largest
{
public int GetLargest(int[] array)
{
if (null == array || 0 == array.Length)
{
throw new Exception("数组不能为空!");
}
int result = array[0];
for (int i = 0; i < array.Length; i++)
{
if (result < array[i])
{
result = array[i];
}
}
return result;
}
}
}
然后写单元测试:
namespace CalcTest
{
using NUnit.Framework;
using System.IO;
[TestFixture]
public class LargestTest2
{
Largest largest ;
[SetUp]
public void init()
{
largest = new Largest();
}
[Test]
public void TestGetLargest()
{
var lines = File.ReadAllLines("http://www.cnblogs.com/LargestTest.txt");
foreach (var line in lines)
{
if (line.StartsWith("#"))
{
continue;
}
string[] arr = line.Split(' ');
int expect = Convert.ToInt32(arr[0]);
var list = new List<int>();
int temp=0;
for (var i = 1; i < arr.Length; ++i)
{
temp = Convert.ToInt32(arr[i]);
list.Add(temp);
}
int[] finalArr = list.ToArray();
int result = largest.GetLargest(finalArr);
Assert.AreEqual(expect, result);
}
}
}
}
{
using NUnit.Framework;
using System.IO;
[TestFixture]
public class LargestTest2
{
Largest largest ;
[SetUp]
public void init()
{
largest = new Largest();
}
[Test]
public void TestGetLargest()
{
var lines = File.ReadAllLines("http://www.cnblogs.com/LargestTest.txt");
foreach (var line in lines)
{
if (line.StartsWith("#"))
{
continue;
}
string[] arr = line.Split(' ');
int expect = Convert.ToInt32(arr[0]);
var list = new List<int>();
int temp=0;
for (var i = 1; i < arr.Length; ++i)
{
temp = Convert.ToInt32(arr[i]);
list.Add(temp);
}
int[] finalArr = list.ToArray();
int result = largest.GetLargest(finalArr);
Assert.AreEqual(expect, result);
}
}
}
}
22.如果想要让Nunit和Visaul Studio无缝地集成,用TestDriven,可以到TestDriven.net下载.
功能远比Nunit强大.有的公司要求测试的覆盖率,TestDriven就提供了这个功能.
除些之外它还支持测试调试,这个功能还是不错的,.当你写的测试方法有问题时,它就派上用场了.
还可以直接在net输出窗口输出测试结果等.