了解 JUnit 核心类、接口及生命周期
2012-03-09 00:00
120 查看
Junit 从问世至今已有 12 年的历史,期间功能不断完善,用户逐渐扩大,已经成为 Java 软件开发中应用最为广泛的测试框架。本文着重介绍 JUnit 的核心接口、核心类以及 TestCase 的生命周期,以便读者从架构层面掌握这个工具。
1997 年,Erich Gamma 和 Kent Beck 为 Java 语言创建了一个简单但有效的单元测试框架,称作 JUnit。JUnit 很快成为 Java 中开发单元测试的框架标准。世界上无数软件项目使用它。本文将介绍 JUnit 的核心接口,核心类以及 JUnit 的生命周期。
JUnit 核心接口及核心类
了解 JUnit 的生命周期之前,先了解 JUnit 的核心接口和类是有必要的,这对于了解 TestCase 的生命周期有很大的帮助。
Test:是 TestCase、TestSuite 的共同接口。
TestCase:Test 的接口的抽象实现,是 Abstract 类,所以不能实例化,能被继承。其中一个构造函数 TestCase(String name),根据输入的参数,创建一个测试实例。参数为该类的以 test 开头的方法名,把它添加到 TestSuite 中,指定仅仅运行 TestCase 中的一个方法。
TestSuite:实现 Test 接口。可以组装一个或者多个 TestCase。待测试类中可能包括了对被测类的多个 TestCase,而 TestSuit 可以保存多个 TestCase,负责收集这些测试,这样就可以一个 Suite 就能运行对被测类的多个测试。
TestResult:保存 TestCase 运行中的事件。TestResult 有
TestListener:是个接口,对事件监听,可供 TestRunner 类使用。
ResultPrinter:实现 TestListener 接口。在 TestCase 运行过程中,对所监听的对象的事件以一定格式及时输出,运行完后,对 TestResult 对象进行分析,输出的统计结果。
BaseTestRunner:所有 TestRunner 的超类。
java Junit.swingui.TestRunner:实现 BaseTestRunner,提供图形界面。从 4.0 版本起,就没有再提供这个类。这是 4.0 版本和之前版本的显著变化之一。
java Junit.textui.TestRunner:实现 BaseTestRunner,提供文本界面。下面将以它做为例子讲解 JUnit 生命周期。
TestCase 实例
了解了前面的几个类,下面将看一个例子:
两种不同参数运行 TestCase
参数 1:
输入:
输出:
参数 2:
输入:
输出:
参数 1:TestCase 名字,该类的所有的以 test 开头的 public 方法都会执行。
参数 2:参数
TestRunner 还提供了其他的参数
TestRunner 处理两种不同的参数
TestRunner
参数一:
首先调用
TestSuite 构造函数中,通过调用
并且都保存在
参数二:
与方法一不同的的是,并不通过反射获得相应的方法,因为参数中指定了特定的方法。直接根据输入参数调用 TestSuite 的
TestCase 实例的运行
生成 TestCase 实例后,两种参数都将调用 TestRunner 的
在
TestResult
TestResult 有两个 List,用来记录 Exception 和 Failure。捕获
清单二:
完整生命周期
整个生命周期将在下图显示:
图 1. Junit 完整生命周期
总结
通过上面的介绍,本文深入地讲解了 JUnit 的核心类和接口,TestCase 的完整生命周期。掌握了这些,开发者有了更加灵活的自用度,可以根据自己特定的项目的特性,定制最合适自身的 MyTestRunner,MyTestResult,MyTestSuite,MyTestListener。从而提高工作效率,发挥 JUnit 的最大作用。
本文出处:http://www.ibm.com/developerworks/cn/java/j-lo-junit-intro/index.html
$(document).ready(function(){dp.SyntaxHighlighter.HighlightAll('code');});
原文链接:
http://blog.csdn.net/cyq1984/article/details/5314222
1997 年,Erich Gamma 和 Kent Beck 为 Java 语言创建了一个简单但有效的单元测试框架,称作 JUnit。JUnit 很快成为 Java 中开发单元测试的框架标准。世界上无数软件项目使用它。本文将介绍 JUnit 的核心接口,核心类以及 JUnit 的生命周期。
JUnit 核心接口及核心类
了解 JUnit 的生命周期之前,先了解 JUnit 的核心接口和类是有必要的,这对于了解 TestCase 的生命周期有很大的帮助。
Test:是 TestCase、TestSuite 的共同接口。
run(TestResult result)用来运行 Test,并且将结果保存到 TestResult。
TestCase:Test 的接口的抽象实现,是 Abstract 类,所以不能实例化,能被继承。其中一个构造函数 TestCase(String name),根据输入的参数,创建一个测试实例。参数为该类的以 test 开头的方法名,把它添加到 TestSuite 中,指定仅仅运行 TestCase 中的一个方法。
TestSuite:实现 Test 接口。可以组装一个或者多个 TestCase。待测试类中可能包括了对被测类的多个 TestCase,而 TestSuit 可以保存多个 TestCase,负责收集这些测试,这样就可以一个 Suite 就能运行对被测类的多个测试。
TestResult:保存 TestCase 运行中的事件。TestResult 有
List<TestFailure> fFailures和
List<TestFailure> fErrors。fFailures 记录 Test 运行中的 AssertionFailedError,而 fErrors 则记录 Exception。Failure 是当期望值和断言不匹配的时候抛出的异常,而 Error 则是不曾预料到的异常,如:ArrayIndexOutOfBoundsException。
TestListener:是个接口,对事件监听,可供 TestRunner 类使用。
ResultPrinter:实现 TestListener 接口。在 TestCase 运行过程中,对所监听的对象的事件以一定格式及时输出,运行完后,对 TestResult 对象进行分析,输出的统计结果。
BaseTestRunner:所有 TestRunner 的超类。
java Junit.swingui.TestRunner:实现 BaseTestRunner,提供图形界面。从 4.0 版本起,就没有再提供这个类。这是 4.0 版本和之前版本的显著变化之一。
java Junit.textui.TestRunner:实现 BaseTestRunner,提供文本界面。下面将以它做为例子讲解 JUnit 生命周期。
TestCase 实例
了解了前面的几个类,下面将看一个例子:
public class TestShoppingCart extends TestCase { double unitPrice = 5; int quantity = 6; double discount=0.2; @Before public void setUp() throws Exception { System.out.println(" Up "); } @After public void tearDown() throws Exception { System.out.println(" Down "); } public void testPay() { double total = unitPrice * quantity; assertEquals(30, total); } public void testPayWithDiscount() { double total = unitPrice * quantity*(1-discount); assertEquals(24.0, total); } }
两种不同参数运行 TestCase
参数 1:
输入:
>java junit.textui.TestRunner TestShoppingCart
输出:
Up testPay! Down Up testPayWithDiscount! Down |
输入:
> java junit.textui.TestRunner -m TestShoppingCart.testPayWithDiscount
输出:
Up testPayWithDiscount! Down |
参数 2:参数
-m,仅仅运行该类的该方法。
TestRunner 还提供了其他的参数
-wait:(最大响应时间),
-v:查看 JUnit 版本号。从输出可以看出,参数一:
testPay(),
testPayWithDiscount()都运行;参数二:仅仅运行参数中的
testPayWithDiscount()。对比两个输出结果,
setUp()在每个方法运行前运行一次,
teardown()在每个方法运行后执行一次。后面将会详细介绍。
TestRunner 处理两种不同的参数
TestRunner
main()方法中,生成一个 TestRunner 实例,调用
start(args)方法。在 start 方法中,JUnit 对输入参数进行处理,首先检查 -m、-v、-wait 等参数,对他们分别进行处理。如果有 -m 参数,将会根据“.”的位置,分割得到 className 和 methodName.
参数一:
首先调用
getTest(),通过 Java 反射实例化 TestSuite:
Class testClass = Class.forName(suiteClassName).asSubclass(TestCase.class); new TestSuite(testClass) |
Class.getDeclaredMethods(),得到这个类的所有 Public 的方法,当然也包括构造函数,test 开头和非 test 开头的 public 方法。对所有方法进行过滤,仅仅保留 public 并且以“test”开头的方法,本例中为
testPay()和
testPayWithDiscount()。然后分别调用 TestSuite 的
createTest()为每个方法生成一个实例:
theClass.getConstructor(String.class).newInstance(new Object[0]); |
Vector<Test> fTests中。
参数二:
与方法一不同的的是,并不通过反射获得相应的方法,因为参数中指定了特定的方法。直接根据输入参数调用 TestSuite 的
createTest(),通过反射直接生成 TestCase 实例。
TestCase 实例的运行
生成 TestCase 实例后,两种参数都将调用 TestRunner 的
doRun()方法。下面将对第二种参数进行详细介绍,介绍一个 TestCase 实例是怎么运行的,并且怎样与 TestResult 和 TestListener 结合。
在
doRun()方法中,实例化 TestResult result, 为 result 加上 Listener (new ResultPrinter()),用来监听 Test 运行中的事件。然后运行
TestResult.Run(test)。
run()方法中调用 TestCase 的
runBare()。
runBare()会把所有的异常都抛出来,result 将接受到所有的异常。
runBare()首先会运行
setup(),接着运行
runTest(), 最后
tearDown()。回头再看前面的 output,就明白了为什么
setup()和
tearDown()会在每个方法运行前和后运行,对于参数二,运行了两次。
TestResult
TestResult 有两个 List,用来记录 Exception 和 Failure。捕获
runBare()抛出的 Exception,首先判断是否为 AssertionFailedError,是则调用
addFailure()把,把异常加到 fFailures。否则则并调用
addError()方法,把异常加到 fErrors 中。
catch (AssertionFailedError e) { addFailure(test, e); } catch (ThreadDeath e) { // don't catch ThreadDeath by accident throw e; } catch (Throwable e) { ddError(test, e); } TestListener 前面提到 result 加上了一个 ResultPrinter,ResultPrinter 会记录运行中的所有 Exception,并且实时地以不同的格式输出。当所有的 Test 都运行完毕后,ResultPrinter 会对 result 进行分析,首先输出运行的时间,接着 printError()输出 fErrors 的个数, printFailures()则输出 fFailures 的个数。 PrintFooter()根据 result.wasSuccessful(),如果成功,则打印 OK 和 test 运行的总次数,如果失败,则打印出 test 总的运行的个数,失败和错误的个数。 参数一的统计输出结果:
|
synchronized void print(TestResult result, long runTime) { printHeader(runTime); printErrors(result); printFailures(result); printFooter(result); }
清单二:
protected void printFooter(TestResult result) { if (result.wasSuccessful()) { getWriter().println(); getWriter().print("OK"); getWriter().println (" (" + result.runCount() + " test" + (result.runCount() == 1 ? "": "s") + ")"); } else { getWriter().println(); getWriter().println("FAILURES!!!"); getWriter().println("Tests run: "+result.runCount()+ ", Failures: "+result.failureCount()+ ", Errors: "+result.errorCount()); } getWriter().println(); }
完整生命周期
整个生命周期将在下图显示:
图 1. Junit 完整生命周期
总结
通过上面的介绍,本文深入地讲解了 JUnit 的核心类和接口,TestCase 的完整生命周期。掌握了这些,开发者有了更加灵活的自用度,可以根据自己特定的项目的特性,定制最合适自身的 MyTestRunner,MyTestResult,MyTestSuite,MyTestListener。从而提高工作效率,发挥 JUnit 的最大作用。
本文出处:http://www.ibm.com/developerworks/cn/java/j-lo-junit-intro/index.html
$(document).ready(function(){dp.SyntaxHighlighter.HighlightAll('code');});
原文链接:
http://blog.csdn.net/cyq1984/article/details/5314222
相关文章推荐
- 了解 JUnit 核心类、接口及生命周期
- Hibernate五个核心接口的初步了解
- 深入了解 Dojo 的核心接口
- 深入了解 Dojo 的核心接口
- 深入了解 Dojo 的核心接口
- 条款41:了解隐式接口和编译期多态
- 深入了解JUnit 4
- 核心资讯基础架构优化(Core Infrastructure Optimization)了解
- Maven 核心概念——生命周期
- Maven核心概念之仓库,生命周期与插件
- 演示对象的生命周期及Session接口
- MyBatis核心接口和类
- effective C++ 条款 41:了解隐式接口和编译期多态
- SpringMVC经典系列-05深入了解SpringMVC的核心原理---【LinusZhu】
- Hibernate 5大核心接口
- JDBC接口核心的API、Statement接口详解
- spring mvc几个重要的核心类和接口
- Hibernate核心开发接口浅析
- junit的核心类
- [EffectiveC++]item41:了解隐式接口和编译器多态