NUnit的原理
上一篇 / 下一篇 2008-06-25 14:30:51 / 个人分类:WEB开发
工具:NUnit的原理
NUnit的原理很简单,就是新建一个TestFixture实例,然后依次调用TestFixture中的Test Case,然后纪录Test Case的运行结果ITPUB个人空间fw)e&K5`
NUnit的核心对象是TestCase, TestSuit, TestResult
TestCase指一个Test Case,比如一个[Test]属性标记的方法ITPUB个人空间hF/]$]zwt kc
TestSuit指一组Test Case,比如一个[TestFixture]属性标记的对象ITPUB个人空间;| sh6EJ3_kMt
TestResult指Test Case运行的结果,TestResult是一个抽象类,在NUnit中,有两个类是继承自TestResult的:TestCaseResult和TestSuiteResult
NUnit是怎样运行Test Case的
NUnit定义了一个处理Test Case的抽象类TestCaseITPUB个人空间 X v?yuS[:Y
TestCase类最重要的方法就是Run()
*Y;i6T1n4[yM0public override TestResult Run(EventListener listener)
Eh3Jg0H2y(K)R O0public abstract void Run(TestCaseResult result);
~rMGW3S1]0TestCase运行的结果会存入一个TestCaseResult对象
调用Run方法如果传入实现了EventListener接口的对象话,就可以在TestCase实际运行之前以及TestCase运行之后进行自定义的处理
Y1~ F6Pg0......ITPUB个人空间w0h2LC#Pw"P5K
listener.TestStarted(this);
i#ba gS`
M0Run(testResult);
k9W$z!X9O&Z2k0listener.TestFinished(testResult);ITPUB个人空间fg2r4[%R*Q*g)r9l"wD
......
NUnit还定义了一个实现抽象类TestCase的通用模版ITPUB个人空间/nq _dJ|
public abstract class TemplateTestCase : TestCase
TemplateTestCase中Run方法的基本框架为
xo,^1|:u,{0public override void Run(TestCaseResult testResult )
9c's8e$Sm)}c0{
I,J#Z [H2Xj0 tryITPUB个人空间4^w+h*@'Lt
{ITPUB个人空间.Dj_+p7x YHV)vR&j.K
InvokeSetUp(); //设置环境
#K;u2Lb|C3R%\0 InvokeTestCase(); //运行Test CaseITPUB个人空间q
M~/n2^Q0A
InvokeTearDown(); //恢复环境
i3LKFU6hB[i\ B0 ProcessNoException(testResult); //无异常退出ITPUB个人空间s+`*J)mp'i
T7B6Y
}
"tGn{QxB0 catch
-R8E-k(F"Le%H|,o0 {ITPUB个人空间+H$HUC` r)\
ProcessException(testResult); //异常处理
5nYsJ!I"v3K5LMd9N0 }
3yDX*Z
c'\ G,]0}
在Run方法中还会计算Test Case实际运行的时间和所用的内存ITPUB个人空间V)Vf6GFa ^{
DateTime start = DateTime.Now;
$Nu\`%zC6w4r-I0long before = System.GC.GetTotalMemory( true );
.... //run test case
long after = System.GC.GetTotalMemory( true );
-j/k*sKO;[0testResult.Leakage = after - before;ITPUB个人空间l+O$OX@ezH#x5d
DateTime stop = DateTime.Now;ITPUB个人空间_$T~8P!T8R+g
Y
TimeSpan span = stop.Subtract(start);
$D;K"mS5gTA9vP0testResult.Time = (double)span.Ticks / (double)TimeSpan.TicksPerSecond;
下面几个类都是继承自TestCase类或者TemplateTestCase类
2rbE.nn;zGFq0NormalTestCase //一般的Test CaseITPUB个人空间c$F%I
}l;d5vx)u
NotRunnableTestCase //不可运行的Test CaseITPUB个人空间 Qdm4x{d5pI9o_k
ExpectedExceptionTestCase //定了期望异常的Test Case
ITPUB个人空间N m'Z P(G*b-[
为什么写的Test Case没有自动运行
Y?K Nc OQ6t0写Test Case时候要注意,Test Case必须是public的,无参数的,无返回值的函数
L$][Fn$MU5m3C/`0参考:
9rHN;zuuA~$p0public class NotRunnableTestCase : TestCase
l_|1u*_9n0]0{
c9E0A2K)s0 public NotRunnableTestCase(MethodInfo method) : base(method.DeclaringType.FullName, method.Name)
6?urS(y
Oj:F#B0 {
~4xrVc#?0 string reason;
if (method.IsAbstract)ITPUB个人空间7F1vt!v6UJD
RJ
reason = "it must not be abstract";
0ZME.[NT:r&of0 else if (method.IsStatic)ITPUB个人空间lP
o Z5\v%t
reason = "it must be an instance method";
VTaQYF0 else if (!method.IsPublic)ITPUB个人空间Ig.P4Te+H}m\
reason = "it must be a public method";ITPUB个人空间"E^J{QqTa
else if (method.GetParameters().Length != 0)
8[D Ip3\5iD0 reason = "it must not have parameters";ITPUB个人空间,L X-Z-yu
else if (!method.ReturnType.Equals(typeof(void)))
,~E Iqv p$V:F2w/H0 reason = "it must return void";
NKI:H1o}V0 elseITPUB个人空间&{\$y:wK5P
reason = "reason not known";
ShouldRun = false;ITPUB个人空间
Bx
O@x;? oy1K w9H
IgnoreReason = String.Format("Method {0}'s signature is not correct: {1}.", method.Name, reason);