TDD, JUnit, TestNG

前两天注意到TheServerSide上一个挺老的新闻TestNG阵营认为JUnit在最新的4.0版本中“抄袭”了他们的Idea,TestNG的Co-Founder分别在自己的Blog上发言来证明(Cedric Beust:JUnit 4 overview,Alexandru Popescu:JUnit 4.0),Erich Gamma则留言反击,听起来满有意思,于是我也顺便研究了一下TestNG。

"…I’m not quite sure what is the driving vision behind JUnit 4 (besides TestNG :-) )".

I’m glad that there is TestNG, but there are also other interesting testing framework efforts. In particular there is NUnit.NUnit has introduced using annotations in testing frameworks a while ago. Most of the requests for annotation based tests came from the dual NUnit/JUnit users. So we are listening to the community.

Posted by: Erich Gamma at June 11, 2005 09:02 AM

先来说说TDD(Test Driven Development)- 测试驱动开发,想了解TDD,最好看看Kent Back的《测试驱动开发》,里面详细的讲述了TDD的原理、实践。不过,我觉得,只有你真正的去用了,才能体会到测试驱动开发给你带来的好处。

我觉得,TDD给我们带来的好处有很多:

1)从功能需求入手,设计对象,在写TestCase的时候其实就是对象设计的时候,这样,TestCase写好写全了,对象也就设计好了;

2)可以在开发阶段找到很多Bug(尤其是很多边缘测试的情况),减少后期Debug的时间;

3)减少由于重构或者Fix其它Bug的时候带来的Regression。

全部测试通过,开发也就结束了,真的很有帮助。

举个例子,比如Xerdoc DSearch中JPEG Parser Plugin的开发。首先从功能需求的角度出发,这个Parser要负责解析出JPEG文件的EXIF头信息,那么ok,我就设计一个ExifInfo的解析Parser类。然后开始写TestCase。

  1. public void testParseExifInfor() {
  2.         String filePath = "P8040002.JPG";
  3.         File picFile = new File(filePath);
  4.  
  5.         ExifInfor exif = new ExifInfor(filePath);
  6.        
  7.         assertTrue(exif != null);
  8.         assertEquals(600, exif.getWidth());
  9.         assertEquals(true, exif.isColor());
  10.          
  11.           ... ...
  12. }

在进行测试用例(TestCase)设计的时候,我们就可以设计出ExifInfor类的基本接口,剩余的工作可以留到重构(Refactoring:是XP Programming中另一个非常棒的概念。)的时候进行了。

当然,测试用例要Cover尽可能多的情况,比如不标准的Exif信息等等,当开发结束,所有的测试都通过的时候,你就可以冲上一杯咖啡,来想想重构的事儿了(当然,重构完毕还是需要用TestCase来检验重构的结果的,呵呵)。

TestNG(Test Next Generation – The next generation of unit testing),顾名思义,目标直指下一代的测试框架。

TestNG比起JUnit来说,变化主要表现在:

1)最大的不同就是TestNG利用了JavaSE 5.0中的Annotations(JSR175)来代替test开头的用例函数名(TestNG说,现有IDE大多都按照函数名排序了,test打头弄得这些函数不好分辨,呵呵)。我觉得这个Idea确实不错,而且本应如此,Annotation就是用来干这个的嘛。不过这个其实不能怪JUnit,JUnit出来的时候Annotations还没有出现在Java语言中。

2)解决JUnit中的多实例化问题。在JUnit中,每一个测试用例都会实例化一份TestCase,同时也会在测试执行前执行setUp,在测试后执行tearDown。这会带来效率的降低,而有些测试,比如数据库链接,也会带来一些其它问题。TestNG用XML配置文件来解决这样的问题。不过,我觉得,简单才是最美,弄成Ant配置那么复杂的话,真够麻烦。

3)TestNG对多线程测试的支持良好,只需要配置即可。JUnit中要想进行多线程测试比较麻烦,需要其它模块,比较著名的是GroboUtils

我觉得很多概念都不错,比如Group Testing,不需要派生TestCase等等,测试用例函数的参数化等等,不过这些还是站在了巨人(JUnit)的肩膀上。我不喜欢的是XML Configuration的部署策略,太麻烦。TestNG给出的是这样的应用场景,一个小组开发,写好所有的测试用例,有的人只需要这几个,有的人需要那几个,因为全部编译测试非常花费时间,这样,更改XML Configuration就可以了,确实如此,不过我实在不喜欢什么东西都用这种配置文件来弄,简单的事情变得复杂,就不好玩儿了。就连Ant之父James Duncan Davidson也觉得Ant现在的脚本太复杂呢,呵呵。

从0到1和从1到2是完全不同的,基于测试开发这个Idea真的是非常棒,这种Test Driven Development真的极大的改变了软件开发的方式。最早的Idea不知道是谁的,我记着从前看Bruce Eckel的Thinking in Java的时候,就有单元测试的影子。插一句,其实,Java中的Assert Keyword,MFC中的Assert宏,也都有TDD的影子,不过还差很多,但是开发理念已经有几分相像了。

至于那些讨论,我觉得实在没有必要,TestNG站在JUnit的肩膀上才发展起来,也不必如此小气。不过个人观点:我还是喜欢JUnit,希望她越来越好 :P

Update:

看到NUnit集成到MonoDevelop中的截图,NUnit就是利用C#中的注解(Annotation)来标识测试函数的。Eric也提到JUnit 4.0其实是参考了NUnit,呵呵。

参考资料:

TestNG crew takes a sneak peek at JUnit 4

TestNG: The next generation of unit testing》 – Thierry Janaudy

Using Assertions in Java Technology》 – Qusay H. Mahmoud

Multithreaded Tests with JUnit

TestNG 使 Java 单元测试轻而易举》 – Filippo Diotalevi

修改历史:

2005.06.26 – 创建

2005.07.08 – 完成

2005.07.16 – 添加NUnit部分

Popularity: 13% [?]

Related entries:

2 Responses to “TDD, JUnit, TestNG”

  1. Meng Yan ( 孟岩 ) @ Weblog » Blog Archive » Tag your Java source code with Tiger’s annotation Says:

    [...] JUnit4.0中,就改用Annotation来创建单元测试,而不再用"test"开头的函数了。这样更自然,而且更符合标准。 [...]

  2. Meng Yan ( 孟岩 ) @ Weblog » Blog Archive » “JUnit4.0 in 10 minutes” learning minutes Says:

    [...] TestNG与JUnit的嘴仗似乎告一段落了,Gunjan Doshi今天发布了一个"JUnit 4.0 in 10 Minutes: A Quick Reference Guide",学习笔记如下。 [...]

Leave a comment

(required)

(required)


Information for comment users
Line and paragraph breaks are implemented automatically. Your e-mail address is never displayed. Please consider what you're posting.

Use the buttons below to customise your comment.


RSS feed for comments on this post | TrackBack URI