本文介绍如使用 JUNIT 3.8.1 框架编写
测试程序。 前提是用户安装了JDK (5 以上)
1, JUNIT 3.8.1 下载
2, JUNIT 3.8.1 框架简介:
JUNIT 3.8.1 框架在 junit.framework 包中定义,共有 10 个类(或者接口)。定义如下几个方面:
1),
测试用例和测试过程,
Test, Assert,TestCase,
AssertionFailedError, ComparisonFailure, Protectable2), 测试结果, TestResult, TestListener, TestFailure,
3), 测试集, TestSuite,
如果采用测试集, 则 TestSuite 的 public void run(TestResult result) 是测试运行的入口函数,该函数会调用每个测试用例 TestCase 的 public void run(TestResult result), 而它会回调 TestResult 的 protected void run(final TestCase test)。
如果不采用测试集,则入口可以直接是TestCase 的 public void run(TestResult result)。
TestResult 的protected void run(final TestCase test)把测试过程分为开始(startTest), 测试(runBare,回调TestCase)和结束(endTest) 三个过程。 其中,测试过程又可再细分为安装(setup),运行(runTest)和收尾(tearDown)三个部分。
- TestResult 可以注册监听器,用于报告测试进度和结果,用户应该编写自己的监听器。即,startTest 和 endTest 可以通过 TestListener 获取。
- 用户可以重载 setup 和 tearDown 来做一些准备和清除工作。
- 用户定义的test 方法被 runTest 通过reflection 执行。
3, 使用 JUNIT 3.8.1 框架编写测试示例
通过上面简介,我们可以知道,编写符合 JUNIT3.8.1 框架的测试用例包括以下几个方面:
1) 编写测试用例,例如:
import junit.framework.*;
public class MyTestCase extends TestCase
{
public void test1() // 测试方法一定要以“test”为开头
{
fail(); // 用户应该添加真正的测试代码,这里只是模拟失败的情况
}
public void test2() // 测试方法一定要以“test”为开头
{
// 用户应该添加真正的测试代码,这里只是模拟成功的情况
}
}
2) 编写监听器,以获取测试进程和测试结果信息
import junit.framework.*;
public class MyTestListener implements TestListener{
public void addError(Test test, Throwable t)
{
System.out.println("Error: " + test + t);
}
public void addFailure(Test test, AssertionFailedError t)
{
System.out.println("Failed: " + test + t);
}
public void endTest(Test test)
{
System.out.println("EndTest: " + test);
}
public void startTest(Test test)
{
System.out.println("StartTest: " + test);
}
}
3),写测试主程序:
import junit.framework.*;
public class MyTestMain
{
public static void main(String[]args)
{
System.out.println("myTest1");
myTest1();
System.out.println("myTest2");
myTest2();
}
public static void myTest1()
{
TestCase test = new MyTestCase();
TestResult result = new TestResult();
result.addListener(new MyTestListener());
test.setName("test1");
test.run(result);
test.setName("test2");
test.run(result);
}
public static void myTest2()
{
TestSuite suite = new TestSuite(MyTestCase.class);
TestResult result = new TestResult();
result.addListener(new MyTestListener());
suite.run(result);
}
}
编译:
javac -classpath .;d:/junit/junit-3.8.1.jar *.java
运行:
java -cp .;../junit-3.8.1.jar MyTestMain
结果: (显示 test1 没过, test2 过了)
myTest1
StartTest: test1(MyTestCase)
Failed: test1(MyTestCase)junit.framework.AssertionFailedError
EndTest: test1(MyTestCase)
StartTest: test2(MyTestCase)
EndTest: test2(MyTestCase)
myTest2
StartTest: test1(MyTestCase)
Failed: test1(MyTestCase)junit.framework.AssertionFailedError
EndTest: test1(MyTestCase)
StartTest: test2(MyTestCase)
EndTest: test2(MyTestCase)
补充:
1,由于 JUNT 框架采用自动探知测试用例中的测试方法(以test开头)的思路,因此,在它的实现中用到了reflection 这个 Java 语言特性。
2,一个需要注意的概念性的问题是,测试集里的一个元素,不仅仅对应一个 TestCase,而且是对应 TestCase 中的一个测试方法(test开头), 所以,“测试用例”这个词,更应该对应测试方法,而不是TestCase 实例本身。
3,回顾一下 Test, TestCase 和 TestSuite 的概念, TestCase 和 TestSuite 都实现了 Test 接口, 但 TestSuite 是个典型的 compositor, 而 TestSuite 在设计上不是很单纯,一方面,他具有单个元素的概念(它的 countTestCases 总是返回1),另一方面,作为多个测试方法的原始包容类,它要接收用户的定义,但最终系统为每个test方法创建了 TestCase 实例。
TestCase 这种两面性,增加了灵活度,但在理解上有点绕弯,但作为使用者来说,可以不用搞得太清楚。“测试用例”这个词的指代也可以模糊一些,只要与test方法对应就行了。