(由于是边看边写,有些内容是根据已有知识推理得来,不一定正确,请各位指正,谢谢)
我们测试一个类,一般都是要测试它的方法。
(Junit v.3.8.1,对主要的类逐个逐个的分析)
TestCase
Junit中分为TestSuit和TestCase,前者包括多个后者,后者一般是对一个类的测试。TestCase是一个抽象类,使用者必须要继承它来写自己的测试用例类。例如(example from Junit source code's commet):
* public class MathTest extends TestCase { * protected double fValue1; * protected double fValue2; * * protected void setUp() { * fValue1= 2.0; * fValue2= 3.0;
* }
* //add whatever u want to test here * }
接下来比如说我们要测试一个名为add的method则我们要在MathTest中定义testAdd(),最好按这种方式确定你的方法名:test +whatever u want to test (第一个字母大写),原因是后面会谈到的TestCase运行你的测试方法的方法,其实如果你用过Eclipse的话就会知道,Eclipse就是按照这个规则自动生成测试方法的方法名的,再有一个就是这样命名也是我们对要测试什么一目了然。比如我们的testAdd()为(同上):
* public void testAdd() { * double result= fValue1 + fValue2; * assertTrue(result == 5.0); * }
现在你可以有两种方法来运行这个testAdd()。第一种如下:
* TestCase test= new MathTest("add") { * public void runTest() { * testAdd(); * } * }; * test.run();
这是定义了一个内部类,覆盖了runTest() 方法,这是最生硬的方法,其实不要参数"add"参数是多余的,我们用的最多的还是下面这种方法。
第二种,使用java的反射机制(最近正在研究这个^_^,派上用场了),如:
* TestCase= new MathTest("testAdd"); * test.run();
这里传递"testAdd"参数是为了用反射机制找到并testAdd(),这个功能恰好是在前一种方法中覆盖掉的runTest() 中实现的,至于是怎么实现的,后面会详细讲。
两种方法都最后调用了run()方法,但是真正运行你的测试方法并不是在这个方法里面,我们从第一种方法中里也看到了,testAdd()是在runTest() 里调用的。其实调用run()是为了对整个测试的过程做一些统计,以及保存测试的结果在TestResult对象里,我们看run()的源代码就知道:
/** * A convenience method to run this test, collecting the results with a * default TestResult object. * * @see TestResult */ public TestResult run() { TestResult result= createResult(); run(result); return result; }
public void run(TestResult result) { result.run(this); }
这些统计处理都是在TestResult里的run(final TestCase test)里实现的,这个方法最终通过this参数调用了TestCase中的runBare()方法:
/** * Runs the bare test sequence. * @exception Throwable if any exception is thrown */ public void runBare() throws Throwable { setUp(); try { runTest(); } finally { tearDown(); } }
大家可能对setUp()和tearDown()特别熟悉吧,对了,这就是在Eclipse里建立测试用例中要你勾选的两个选项,现在知道是干什么用的了吧,setUp()是建立你的测试环境,tearDown()则是做一些收尾工作,比如如果你测试与数据库有关的类的话,这个方法里大概就要关闭你打开的数据库连接了。
所以到这里大家也看到了,重点就在runTest(),下面我们来分析这个方法:
protected void runTest() throws Throwable { assertNotNull(fName); Method runMethod= null; try { runMethod= getClass().getMethod(fName, null); } catch (NoSuchMethodException e) { fail("Method ""+fName+"" not found"); } if (!Modifier.isPublic(runMethod.getModifiers())) { fail("Method ""+fName+"" should be public"); }
try { runMethod.invoke(this, new Class[0]); }
//the left code
这里要说一下 assertNotNull(fName),先判断一下要调用的方法名是否为空,如果不为空,再接下去用反射机制调用这个方法,这里要用到方法名来查找方法,也就是前面提到的为什么要那样命名你的测试方法的原因。 assertNotNull(fName)方法会抛出Erro,而不是Exception,所以不需要try-catch。
到这里TestCase的主要方法,都差不多介绍完了,但是我还要说一点。在看Junit的源代码之前,我只用Eclipse对它有过简单的应用,Eclipse帮我们做了很多事情,这个在看Junit的源代码时才知道。原来每测试一个方法,都要初始化一个TestCase实例。
今天就看到这里,也写到这里了。Junit更另我感兴趣的是整个框架的结构,这个以后再说,我还每看完呢!(^_^)
(未完待续)
<script type="text/javascript"> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>