为了项目的质量,以及节省以后的维护测试成本,决定开始学习一种单元测试工具,面对庞大的XUnit家族,决定从JUnit下手,毕竟擒贼先擒王嘛。
- JUnit简介
JUnit团队为JUnit框架设置了三个目标,这三个目标正好是我们项目开发中对于单元测试最好的功能定义。Keep the bar green to keep the code clean.
*框架必须帮助我们编写有用的测试
*框架必须帮助我们创建随着时间的流逝仍然保持有用的测试
*框架必须通过复用代码降低我们编写测试的成本
可以在http://www.junit.org/index.htm下载到最新工具包,目前的版本是JUnit4.4。4.4版本相比于3.8.1版本最显著的是没有自带Swing界面,但是如果在Eclipse中使用,还是可以看到那熟悉的画面的,呵呵。
解压缩后测试是否能正常运行,步骤如下:
在命令窗口中设置classpath,“set classpath=%classpath%C:/junit4.4/junit-4.4.jar;”
执行下面的语句,“java org.junit.runner.JUnitCore org.junit.tests.AllTests”,正常情况下,会显示329个Test项目测试通过。
如果你使用的是3.8.1,那么,“set classpath=%classpath%C:/junit3.8.1/junit.jar;”
执行“ java Junit.swingui.TestRunner Junit.samples.AllTests”--Swing界面
执行“java Junit.textui.TestRunner Junit.samples.AllTests”--Text界面 -
简单的例子
//被测试类,Calculator.java
public class Calculator
{
public double add(double num1, double num2)
{
return num1+num2;
}
}
//测试类,TestCalculaotr.java
import junit.framework.TestCase;
public class TestCalculator extends TestCase
{
public void testAdd()
{
Calculator calculator = new Calculator();
double result = calculator.add(10, 50);
assertEquals(60, result, 0);
}
} -
JUnit核心类/接口
类/接口
责任
Assert
当条件成立时Assert方法保持沉默,但若条件不成立就抛出异常。
TestResult
TestResult包含了测试中所有的错误或者失败。
Test
可以运行Test并把结果传给TestResult。
TestListener
测试中若产生事件(开始、结束、错误、失败)会通知TestListener。
TestCase
TestCase定义了可用于运行多项测试的环境(或者说固定设备)
TestSuite
TestSuite运行一组test case(他们可能包含其他TestSuite),它是Test的组合。
BaseTestRunner
test runner是用来启动测试的用户界面,BaseTestRunner是所有test runner的超类。
-
使用TestSuite
当需要把一些test case联系起来,进行连续测试的时候就要创建自己的test suite,虽然JUnit会创建默认的test suite把一个test类中所有的test case都测试一遍,但有时候我们可能想一次性测试所有的test类或者指定的几个test case。
下面通过一个典型的TestAll类来说明test suite的组织方式。
这里介绍下TestSuite中用到的设计模式理论:
Composite模式,“把对象组合(composite)成树状结构来表示部分-整体的层次关系。Composite模式可以让客户一致的对待单个对象和对象的组合。”JUnit用Test接口来运行一个单独的测试,或者是多个测试的集合的集合的集合,这就是Composite的例子。当你给TestSuite增加一个对象时,你实际上增加的是Test,而不只是一个TestCase。因为TestSuite和TestCase都实现了Test接口。//典型的TestAll类,TestAll.java
import junit.framework.Test;
import junit.framework.TestSuite;
import junitbook.sampling.TestDefaultController;
public class TestAll
{
public static Test Suite()
{
TestSuite suite = new TestSuite("All tests from part 1");
suite.addTestSuite(TestCalculator.class);
suite.addTestSuite(TestDefaultController.class);
// if TestDefaultController had a suite method
// (or alternate suite methods) you could also use
// suite.addTestSuite(TestDefaultController.suite());
return suite;
}
}*建立一个suite方法,以便调用其它test或者suite
*给这个TestSuite一个标识,以便区别彼此
*可以用addTestSuite方法添加想要一起运行的TestCase或者TestSuite对象,因为addTestSuitie方法接受的参数是Test类型的对象,而TestCase和TestSuite都实现了Test接口。Command模式。“把请求封装成一个对象,这样你就可以用不同的请求、队列或者日志请求把客户参数化,还能支持可撤销的操作。”使用Test接口来提供公共的run方法是Command模式的例子。
-
使用TestResult收集信息
所有TestSuite都有一个对应的TestResult。TestResult负责收集TestCase的执行结果,失败就会产生一个TestFailure,并存储在TestResult中。TestRunner使用TestResult来报告测试结果。如果没有TestFailuer,则显示green bar,反之是red bar,并输出失败测试的数目和他们的松他stack trace。
TestResult的设计模式根据:
Conllecting Parameter模式。“当你需要从几个方法中收集结果时,那你需要给方法增加一个参数,并传递一个能收集这个参数的对象。” -
用TestListener来观察结果
JUnit框架提供了TestListener接口,以帮助对象访问TestResult对象并创建有用的报告。TestRunner实现了TestListener,TestRunner以TestListener的身份注册到TestResult,这是Observer模式的例子。
TestListener的设计模式根据:
Observer模式。“在对象之间定义一个一对多的依赖关系,这样当一个对象改变了状态,那么所有依赖于它的对象都将收到通知并更新。” - 用TestCase来工作
TestCase主要包含两个部件:fixture和单元测试
fixtrue--运行一个或多个测试所需的公用资源或数据集合。TestCase通过setUp和tearDown方法来自动创建和销毁fixture。
--to be continue