1、JUnit的定义
=========
JUnit is an open source Java testing framework used to write and run repeatable tests。
说白了,JUnit 是一个集成测试工具,能实现测试的自动化。
这里说的是单元测试:属于软件工程里的白盒测试,也就是测试某个类的某个方法的功能。
2、JUnit的测试思想
============
如果你要写一段代码:
先用 junit 写测试,然后再写代码
写完代码,运行测试,测试失败
修改代码,运行测试,直到测试成功
XP 中推崇的 test first design 就是基于以上技术。
不过,似乎不可行。以下面的HelloWorldTest为例,如果没有HelloWorld.class存在,则编译到HelloWorld world = new HelloWorld();时就会报错。
这不是与“先写测试,后写代码”的思想相左吗?
3、“先写测试,再写代码”的好处
================
a)从技术上强制你先考虑一个类的功能,也就是这个类提供给外部的接口,而不至于太早
陷入它的细节。这是面向对象提倡的一种设计原则。
b)好的测试其实就是一个好的文档。这个类使用者往往可以通过查看这个类的测试代码了解它的功能。特别的,如果你拿到别人的一个程序,对他写测试是最好的了解这个程序的功能的方法。 xp的原则是make it simple,不是很推荐另外写文档,因为项目在开发过程中往往处于变动中,如果在早期写文档,以后代码变动后还得同步文档,多了一个工作,而且由于项目时间紧往往文档写的不全或与代码不一致,与其这样,不如不写。而如果在项目结束后再写文档,开发人员往往已经忘记当时写代码时的种种考虑,况且有下一个项目的压力,管理人员也不愿意再为旧的项目写文档。导致以后维护的问题。
c)没有人能保证需求不变动,以往项目往往对需求的变动大为头疼,害怕这个改动会带来其他地方的错误。为此,除了设计好的结构以分割项目外(松耦合),但如果有了测试,并已经建立了一个好的测试框架,对于需求的变动,修改完代码后,只要重新运行测试代码,如果测试通过,也就保证了修改的成功,如果测试中出现错误,也会马上发现错在哪里。修改相应的部分,再运行测试,直至测试完全通过。
4、Java下的team开发开发模式
==================
一般采用 cvs(版本控制) + ant(项目管理) + junit(集成测试) 的模式:
每天早上上班,每个开发人员从 cvs server 获取一个整个项目的工作拷贝。
拿到自己的任务,先用 junit 写今天的任务的测试代码。
然后写今天任务的代码,运行测试,直到测试通过,任务完成
在下班前一两个小时,各个开发人员把任务提交到 cvs server
然后由主管对整个项目运行自动测试,哪个测试出错,就找相关人员修改,直到所有测试通过。下班...
5、如何安装?
=======
1、在http://www.junit.org/下载最新的junit,我下载的是junit3.8.1.zip。
2、将下载的压缩包解压到安装目录下,我安装在d:/junit3.8.1。
3、将安装目录下的junit.jar加到classapth中去,这样就安装成功了。
6、如何测试运行正常?
===========
1、在d:/juni3.8.1/junit/samples/目录下键入
java -classpath %CLASSPATH%;. junit.textui.TestRunner SimpleTest
如果出现下列信息:
.
Time: 0.01
OK (1 test)
则表示安装成功。
也可用graphics方式测试:
java -classpath %CLASSPATH%;. junit.swingui.TestRunner SimpleTest
2、或自己写一个例子进行测试:
a)将以下代码键入编辑器中,并存为SimpleTest.java。
import junit.framework.TestCase;
public class SimpleTest extends TestCase {
public SimpleTest (String name) {
super(name);
}
public void testTest() {
assertTrue(true);
}
}
b)编译SimpleTest.java
javac -d . -classpath %CLASSPATH% SimpleTest.java
c)运行SimpleTest
java -classpath %CLASSPATH%;. SimpleTest
7、junit.jar中部分主要类的组织结构
=====================
junit.framework.Assert
.AssertionFailedError
.ComparisonFailure
.Protectable
.Test
.TestCase
.TestFailure
.TestListener
.TestResult
.TestSuite
junit.textui.ResultPrinter
.TestRunner
junit.swingui.AboutDialog
.CounterPanel
.DefaultFailureDetailView
.FailureRunView
.ProgressBar
.StatusLine
.TestHierarchyRunView
.TestRunContext
.TestRunner
.TestRunView
.TestSelector
.TestSuitePanel
.TestTreeModel
8、编写测试类的基本步骤
=============
使用JUnit编写测试代码的一般步骤是:
(1)引入JUnit框架包。import junit.framework.*。
(2)定义测试类名称,一般是将要测试的类名后附加Test。
(3)测试类继承JUnit的TestCase类。
(4)实现类的构造方法,可以在构造方法中简单的调用super(name)即可。
(5)实现类的main()方法,在main()方法中简单调用junit.textui.TestRunner.run(SimpleTest.class)来指定执行测试类。
(6)重载setUp()和tearDown()方法,setUp()方法用于执行每个测试用例时进行环境的初始化工作
(比如打开数据库连接),tearDown()方法用于执行每个测试用例后清除环境(比如关闭数据库连接)。
(7)编写每个测试用例,写一些testXXXX()方法(一般是在要测试的方法前附加test)。
9、如何创建测试案例(示例)?
===============
测试类完整的代码框架如下所示:
import junit.framework.*;
public class HelloWorldTest extends TestCase {
/**
* 构造函数
*/
public HelloWorldTest(String name) {
super(name);
}
/**
* 主方法
*/
public static void main(String args[]) {
junit.textui.TestRunner.run(HelloWorldTest.class);
}
/**
* 测试前的初始化 ---> 执行setUp()方法,初始化你需要的任何值
*/
protected void setUp() {
}
/**
* 清除测试环境 ---> 调用tearDown(),取消初始化并进到下一个测试
*/
protected void tearDown(){
}
/**
* 测试用例1
*/
public void testSayHello() {
HelloWorld world = new HelloWorld();
//assert( world!=null );
assertEquals("Hello World", world.sayHello() );
}
}
javac -d . -classpath %CLASSPATH% HelloWorldTest.java
java -classpath %CLASSPATH%;. HelloWorldTest
--------------------------------------------------------------------
/*
* HelloWorld.java
*/
class HelloWorld {
public String sayHello() {
return "Hello World";
}
public static void main(String[] args) {
HelloWorld world = new HelloWorld();
System.out.println(world.sayHello());
}
}
javac -d . HelloWorld.java
--------------------------------------------------------------------
将HelloWorld.java中return "Hello World";该成return "Hello Worl!";试试看会有什么提示出现。
10、什么是测试包(test suit)?
所谓测试包(test suite)其实就是同一会话中应当执行的测试集合。
测试包把测试组织在一起执行,而不论测试是否在同一文件里。
清单A显示我们的测试包包含两个测试:
Listing A: Test suite
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTest(new XMLTest("testPersonCount"));
suite.addTest(new XMLTest("testContainsPerson"));
return suite;
}
11、如何利用测试包执行测试?
执行测试需要创建可执行类来调用Junit测试运行器。运行器(runner)负责执行测试包(test suite),运行所有的测试并输出测试结果。
清单B显示了如何把测试包集成到测试运行器中:
Listing B: XMLTestRunner.java
import junit.framework.Test;
import junit.framework.TestSuite;
import XMLTest;
public class XMLTestRunner {
//public static Test suite() {
// TestSuite suite = new TestSuite();
// suite.addTest(new XMLTest("testPersonCount"));
// suite.addTest(new XMLTest("testContainsPerson"));
// return suite;
//}
/**
*显示了如何把类的名字传递给测试包构造器来自动装载测试。
*/
public static Test suite() {
return new TestSuite(XMLTest.class);
}
public static void main(String[] args) {
junit.textui.TestRunner.run(suite());
}
}
12、如何创建测试包?-- 手工创建与自动创建
=======================
/**
*手工创建:
*下面这个简单的测试运行器负责创建测试包,首先添加各个测试然后添加整个测试包。
*/
import junit.framework.Test;
import junit.framework.TestSuite;
public class TestRunner {
public static TestSuite suite() {
TestSuite t = new TestSuite();
t.addTest(new HelloWorldTest("testSayHello"));
t.addTest(new SimpleTest("testTest"));
t.addTestSuite(TestRunner.class);
return t;
}
public static void main(String args[]) {
junit.textui.TestRunner.run(suite());
}
}
运行: java -classpath %CLASSPATH%;. TestRunner
(我的TestRunner.class放在与test同级的test目录下)
/**
*自动创建:
*从命令行上读取测试目录,遍历整个目录寻找扩展名为“.class”的文件,然后把它们加到测试包里。
*/
import junit.framework.Test;
import junit.framework.TestSuite;
import java.lang.ClassNotFoundException;
import java.io.*;
import java.util.Vector;
public class AllRunner {
public static void class_list(File directory, TestSuite t) {
if (directory.isDirectory()) {
String[] files = directory.list();
for (int i = 0; i < files.length; i++) {
File f = new File(directory, files[i]);
if (f.isFile() && f.getName().endsWith(".class")) {
int len = f.getName().length();
String n = f.getName().substring(0, len - 6);
try {
t.addTestSuite(Class.forName(n));
} catch (java.lang.ClassNotFoundException e) {
System.out.println(e);
}
}
}
}
}
public static void main(String args[]) {
TestSuite t = new TestSuite("请输入欲测试的目录名: " + args[0]);
AllRunner.class_list(new File(args[0]), t);
junit.textui.TestRunner.run(t);
}
}
技巧:将所有的测试案例放到一个tmp目录下,运行
java -classpath %CLASSPATH%;. AllRunner ../tmp
(我的AllRunner.class放在与test同级的目录test目录下)
就这个例子来说,创建的测试运行器运行了指定目录下的所有测试,并把结果屏幕显示。当然,我们动态创建的测试包假定所有的测试都要运行而且按照从目录中以字母顺序读取的顺序运行。
不对将执行的测试进行选择也是一种可能的测试需求,不过,在这种情况下你就只能手工地把测试加到测试包里。
注意:我们的测试运行器(TestRunner)采用Java类装载器导入类,所以装载器要装载的类一定要位于类路径下(因此我已将d:/j2sdk1.4/mywork下的class目录加到CLASSPATH中去了)。
测试运行器的输出结果就是测试结果,因为输出结果表示了目录下所有测试的状态,所以这种测试对我们的开发工作很有帮助。
。
13、如何与 Ant 集成?
================
集成Junit的Ant可以帮助我们快速地测试系统的变动。Jakarta Project给Ant创建了集成Junit的任务。这些任务可以自动地运行测试同时产生输出结果和报告。
14、如何生成 HTML 报告
==============
15、如何放置test文件?
==============
与原文件分开放置,但结构与包相同。如下所示:
src
com
xyz
SomeClass.java
test
com
xyz
SomeClass.java