CSDN博客

img sarsor

【原创】Junit源码分析(-)

发表于2004/7/7 22:08:00  1334人阅读

(由于是边看边写,有些内容是根据已有知识推理得来,不一定正确,请各位指正,谢谢)

我们测试一个类,一般都是要测试它的方法。

(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更另我感兴趣的是整个框架的结构,这个以后再说,我还每看完呢!(^_^)

(未完待续)

0 0

相关博文

我的热门文章

img
取 消
img