单元测试要运用到实际项目中去,必须把单元测试
代码和项目通过某种途径联系在一起。
@H_
404_3@比如,在我的学习笔记1中,有一个工程:WindowsApplication12,这个工程中有Class1这个类,该类就是项目的实际
代码,随后我在该工程中
添加一个Class1Test的测试类,用来测试Class1中的一些
方法。
@H_
404_3@这个过程,就是一种结合
方法:对每个需要测试的类,都在该类的工程下建立一个测试类。
@H_
404_3@
@H_
404_3@在我的实际经验中,接触到如下几种
方法,以下进行举例说明,每种
方法都有其特定使用环境,优缺点,供大家参考:
@H_
404_3@1,单元测试
代码,直接写在需要被测试的类中。
@H_
404_3@solution结构如下:
@H_
404_3@
@H_
404_3@
@H_
404_3@
代码如下:
@H_
404_3@
Imports
NUnit.Framework@H_404_3@@H_404_3@
<
TestFixture()
>
_@H_404_3@
Public
ClassClass1
ClassClass1@H_404_3@@H_404_3@'''-----------------------------------------------------------------------------@H_404_3@'''<summary>@H_404_3@'''查找最大值@H_404_3@'''</summary>@H_404_3@'''<paramname="list">传入整数数组</param>@H_404_3@'''<returns>返回数组中的最大值</returns>@H_404_3@'''<remarks>@H_404_3@'''</remarks>@H_404_3@'''<history>@H_404_3@'''[TonyGong]5/25/2006Created@H_404_3@'''</history>@H_404_3@'''-----------------------------------------------------------------------------@H_404_3@FunctionFindMax()FunctionFindMax(ByVallistAsInt32())AsInt32@H_404_3@DimiAsInt32@H_404_3@DimmaxAsInt32=Int32.MinValue@H_404_3@@H_404_3@Fori=0Tolist.Length-1@H_404_3@Iflist(i)>maxThen@H_404_3@max=list(i)@H_404_3@EndIf@H_404_3@Next@H_404_3@@H_404_3@Returnmax@H_404_3@@H_404_3@EndFunction@H_404_3@@H_404_3@@H_404_3@'''-----------------------------------------------------------------------------@H_404_3@'''<summary>@H_404_3@'''测试Class1类的FindMax方法@H_404_3@'''</summary>@H_404_3@'''<remarks>@H_404_3@'''</remarks>@H_404_3@'''<history>@H_404_3@'''[TonyGong]5/25/2006Created@H_404_3@'''</history>@H_404_3@'''-----------------------------------------------------------------------------@H_404_3@<Test()>_@H_404_3@PublicSubFindMaxTest()SubFindMaxTest()@H_404_3@'@H_404_3@Dimlist1()AsInt32={1,3,10,4}@H_404_3@Dimlist2()AsInt32={1,4,10}@H_404_3@Dimlist3()AsInt32={10,1,4}@H_404_3@Dimlist4()AsInt32={-2,-1,-3}@H_404_3@@H_404_3@DimmyAsNewClass1@H_404_3@'测试数组list1中的最大整数是不是10。@H_404_3@Assert.AreEqual(10,my.FindMax(list1))@H_404_3@@H_404_3@'测试边界值@H_404_3@Assert.AreEqual(10,my.FindMax(list2))@H_404_3@Assert.AreEqual(10,my.FindMax(list3))@H_404_3@@H_404_3@'测试负数数组,数组中最大值应该是-1@H_404_3@Assert.AreEqual(-1,my.FindMax(list4))@H_404_3@@H_404_3@EndSub@H_404_3@@H_404_3@@H_404_3@EndClass
@H_404_3@@H_404_3@
@H_404_3@运行Nunit,结果如下:@H_404_3@@H_404_3@@H_404_3@这种方法的优点很明显:由于测试代码同被测试的方法放在一个类中,所以private等方法很容易被测试。但同时缺点也很明显,该类会被写得很复杂,估计很少会有人喜欢看这种代码,而且万一客户不需要这些代码的话,在最后部署的时候,关del测试代码,估计也是个大问题。@H_404_3@@H_404_3@2,每写一个需要被测试的类,就写当前工程下新建一个相应的测试类,名字可以在被测试类后面加上Test以示区别。@H_404_3@solution结构如下:@H_404_3@@H_404_3@@H_404_3@代码就不写了,大致就是我在笔记1,2中举的例子。@H_404_3@@H_404_3@这种方法的优点是结构比较清晰,在比较小的工程中使用还算不错,修改测试代码也比较方法。缺点同样是部署时删除单元测试代码比较麻烦,同时solution太大,有很多project时,有很大局限性。@H_404_3@@H_404_3@3,solution有很多个工程时,专门新增加一些工程,用于写单元测试,比如有一个ClassLibrary3工程,则建一个TestForClassLibrary3工程,单元测试类放到这个工程中去。@H_404_3@solution结构如下:@H_404_3@@H_404_3@注意,测试工程要引用被测试工程。@H_404_3@@H_404_3@代码如下:@H_404_3@
Public
ClassClass1
ClassClass1@H_404_3@'''-----------------------------------------------------------------------------@H_404_3@'''<summary>@H_404_3@'''查找最大值@H_404_3@'''</summary>@H_404_3@'''<paramname="list">传入整数数组</param>@H_404_3@'''<returns>返回数组中的最大值</returns>@H_404_3@'''<remarks>@H_404_3@'''</remarks>@H_404_3@'''<history>@H_404_3@'''[TonyGong]5/25/2006Created@H_404_3@'''</history>@H_404_3@'''-----------------------------------------------------------------------------@H_404_3@FunctionFindMax()FunctionFindMax(ByVallistAsInt32())AsInt32@H_404_3@DimiAsInt32@H_404_3@DimmaxAsInt32=Int32.MinValue@H_404_3@@H_404_3@Fori=0Tolist.Length-1@H_404_3@Iflist(i)>maxThen@H_404_3@max=list(i)@H_404_3@EndIf@H_404_3@Next@H_404_3@@H_404_3@Returnmax@H_404_3@@H_404_3@EndFunction@H_404_3@@H_404_3@EndClass
@H_404_3@
@H_404_3@
Imports
NUnit.Framework@H_404_3@
Imports
ClassLibrary3@H_404_3@@H_404_3@
<
TestFixture()
>
_@H_404_3@
Public
ClassClass1Test
ClassClass1Test@H_404_3@PublicSubNew()SubNew()@H_404_3@@H_404_3@EndSub@H_404_3@@H_404_3@'''-----------------------------------------------------------------------------@H_404_3@'''<summary>@H_404_3@'''测试Class1类的FindMax方法@H_404_3@'''</summary>@H_404_3@'''<remarks>@H_404_3@'''</remarks>@H_404_3@'''<history>@H_404_3@'''[TonyGong]5/25/2006Created@H_404_3@'''</history>@H_404_3@'''-----------------------------------------------------------------------------@H_404_3@<Test()>_@H_404_3@PublicSubFindMaxTest()SubFindMaxTest()@H_404_3@'@H_404_3@Dimlist1()AsInt32={1,my.FindMax(list4))@H_404_3@@H_404_3@EndSub@H_404_3@@H_404_3@EndClass
@H_404_3@
@H_
404_3@
由于是以工程为单位,所以部署起来很容易,只要把这几个工程去掉就可以了,将来再要用,也只要加上就可以了。不过操作相对来说比较繁琐,没有前2种方法便捷。@H_404_3@@H_404_3@4,以上3种方法都需要在项目的solution中增加东西,但如果你的项目不允许你增加任何测试类或工程(虽然感觉很愚蠢,但的确很多公司不允许程序员这么做),或者你根本没有权限增加工程或文件,这3种方法将都不能使用,这时可以用第4种方法。@H_404_3@比如你想测试ClassLibrary3工程下的Class1类,你可以先build你的项目,生成ClassLibrary3工程的dll文件,然后在你本地建一个测试工程,引用这个dll,就可以不需要修改你的项目了。@H_404_3@测试solution结构如下(这个solution是在你电脑本地的,与你的项目没有关系):@H_404_3@@H_404_3@@H_404_3@测试代码如下:@H_404_3@
Imports
NUnit.Framework@H_404_3@@H_404_3@
<
TestFixture()
>
_@H_404_3@
Public
ClassClass1Test
ClassClass1Test@H_404_3@PublicSubNew()SubNew()@H_404_3@@H_404_3@EndSub@H_404_3@@H_404_3@'''-----------------------------------------------------------------------------@H_404_3@'''<summary>@H_404_3@'''测试Class1类的FindMax方法@H_404_3@'''</summary>@H_404_3@'''<remarks>@H_404_3@'''</remarks>@H_404_3@'''<history>@H_404_3@'''[TonyGong]5/25/2006Created@H_404_3@'''</history>@H_404_3@'''-----------------------------------------------------------------------------@H_404_3@<Test()>_@H_404_3@PublicSubFindMaxTest()SubFindMaxTest()@H_404_3@'@H_404_3@Dimlist1()AsInt32={1,my.FindMax(list4))@H_404_3@@H_404_3@EndSub@H_404_3@@H_404_3@EndClass
@H_404_3@@H_404_3@
@H_
404_3@这种
方法的最大优点是不需要
修改你的项目,不过缺点也很多,不够灵活,操作复杂等。
@H_
404_3@
@H_
404_3@我个人比较多用2,3,在很小的模块中有时会用1,不过比起用1来,可能使用TestDriven.NET更加方便些,这个我打算后面单独写篇
文章。
@H_
404_3@
@H_
404_3@以上是我平时的一些经验,可能有很大不足,希望指正。