Junit使用简明手册.docx
- 文档编号:30618624
- 上传时间:2023-08-18
- 格式:DOCX
- 页数:31
- 大小:61.67KB
Junit使用简明手册.docx
《Junit使用简明手册.docx》由会员分享,可在线阅读,更多相关《Junit使用简明手册.docx(31页珍藏版)》请在冰豆网上搜索。
Junit使用简明手册
JUnit是什么?
JUnit是一个开发源代码的Java测试框架,用于编写和运行可重复的测试。
他是用于单元测试框架体系xUnit的一个实例(用于java语言)。
它包括以下特性:
1、用于测试期望结果的断言(Assertion)
2、用于共享共同测试数据的测试工具
3、用于方便的组织和运行测试的测试套件
4、图形和文本的测试运行器
JUnit最初是由ErichGamma(GoF之一)和KentBeck(xp和refactor的先驱之一)编写的.
需要说明的是junit一般是用来进行单元测试的,因此需要了解被测试代码的内部结构(即所谓的白盒测试),另外junit是在xp编程和重构(refactor)中被极力推荐使用的工具,因为在实现自动单元测试的情况下可以大大的提高开发的效率,但是实际上编写测试代码也是需要耗费很多的时间和精力的,那么使用这个东东好处到底在哪里呢?
笔者认为是这样的:
1、对于xp编程而言,要求在编写代码之前先写测试,这样可以强制你在写代码之前好好的思考代码(方法)的功能和逻辑,否则编写的代码很不稳定,那么你需要同时维护测试代码和实际代码,这个工作量就会大大增加。
因此在xp编程中,基本过程是这样的:
构思-》编写测试代码-》编写代码-》测试,而且编写测试和编写代码都是增量式的,写一点测一点,在编写以后的代码中如果发现问题可以较块的追踪到问题的原因,减小回归错误的纠错难度
2、对于重构而言,其好处和xp编程中是类似的,因为重构也是要求改一点测一点,减少回归错误造成的时间消耗。
3、对于非以上两种情况,我们在开发的时候使用junit写一些适当的测试也是有必要的,因为一般我们也是需要编写测试的代码的,可能原来不是使用的junit,如果使用junit,而且针对接口(方法)编写测试代码会减少以后的维护工作,例如以后对方法内部的修改(这个就是相当于重构的工作了)。
另外就是因为junit有断言功能,如果测试结果不通过会告诉我们那个测试不通过,为什么,而如果是想以前的一般做法是写一些测试代码看其输出结果,然后再由自己来判断结果使用正确,使用junit的好处就是这个结果是否正确的判断是它来完成的,我们只需要看看它告诉我们结果是否正确就可以了,在一般情况下会大大提高效率。
JUnit入门
cherami整理
安装JUnit
安装很简单,先到以下地址下载一个最新的zip包:
下载完以后解压缩到你喜欢的目录下,假设是JUNIT_HOME,然后将JUNIT_HOME下的junit.jar包加到你的系统的CLASSPATH环境变量中,对于IDE环境,对于需要用到的junit的项目增加到lib中,其设置不同的IDE有不同的设置,这里不多讲。
如何使用JUnit写测试?
最简单的范例如下:
1、创建一个TestCase的子类:
packagejunitfaq;
importjava.util.*;
importjunit.framework.*;
publicclassSimpleTestextendsTestCase{
publicSimpleTest(Stringname){
super(name);
}
2、写一个测试方法断言期望的结果:
publicvoidtestEmptyCollection(){
Collectioncollection=newArrayList();
assertTrue(collection.isEmpty());
}
注意:
JUnit推荐的做法是以test作为待测试的方法的开头,这样这些方法可以被自动找到并被测试。
3、写一个suite()方法,它会使用反射动态的创建一个包含所有的testXxxx方法的测试套件:
publicstaticTestsuite(){
returnnewTestSuite(SimpleTest.class);
}
4、写一个main()方法以文本运行器的方式方便的运行测试:
publicstaticvoidmain(Stringargs[]){
junit.textui.TestRunner.run(suite());
}
}
5、运行测试:
以文本方式运行:
javajunitfaq.SimpleTest
通过的测试结果是:
.
Time:
0
OK(1tests)
Time上的小点表示测试个数,如果测试通过则显示OK。
否则在小点的后边标上F,表示该测试失败。
每次的测试结果都应该是OK的,这样才能说明测试是成功的,如果不成功就要马上根据提示信息进行修正了。
如果JUnit报告了测试没有成功,它会区分失败(failures)和错误(errors)。
失败是你的代码中的assert方法失败引起的;而错误则是代码异常引起的,例如ArrayIndexOutOfBoundsException。
以图形方式运行:
javajunit.swingui.TestRunnerjunitfaq.SimpleTest
通过的测试结果在图形界面的绿色条部分。
以上是最简单的测试样例,在实际的测试中我们测试某个类的功能是常常需要执行一些共同的操作,完成以后需要销毁所占用的资源(例如网络连接、数据库连接,关闭打开的文件等),TestCase类给我们提供了setUp方法和tearDown方法,setUp方法的内容在测试你编写的TestCase子类的每个testXxxx方法之前都会运行,而tearDown方法的内容在每个testXxxx方法结束以后都会执行。
这个既共享了初始化代码,又消除了各个测试代码之间可能产生的相互影响。
JUnit最佳实践
MartinFowler说过:
“当你试图打印输出一些信息或调试一个表达式时,写一些测试代码来替代那些传统的方法。
”一开始,你会发现你总是要创建一些新的Fixture,而且测试似乎使你的编程速度慢了下来。
然而不久之后,你会发现你重复使用相同的Fixture,而且新的测试通常只涉及添加一个新的测试方法。
你可能会写许多测试代码,但你很快就会发现你设想出的测试只有一小部分是真正有用的。
你所需要的测试是那些会失败的测试,即那些你认为不会失败的测试,或你认为应该失败却成功的测试。
我们前面提到过测试是一个不会中断的过程。
一旦你有了一个测试,你就要一直确保其正常工作,以检验你所加入的新的工作代码。
不要每隔几天或最后才运行测试,每天你都应该运行一下测试代码。
这种投资很小,但可以确保你得到可以信赖的工作代码。
你的返工率降低了,你会有更多的时间编写工作代码。
不要认为压力大,就不写测试代码。
相反编写测试代码会使你的压力逐渐减轻,应为通过编写测试代码,你对类的行为有了确切的认识。
你会更快地编写出有效率地工作代码。
下面是一些具体的编写测试代码的技巧或较好的实践方法:
1.不要用TestCase的构造函数初始化Fixture,而要用setUp()和tearDown()方法。
2.不要依赖或假定测试运行的顺序,因为JUnit利用Vector保存测试方法。
所以不同的平台会按不同的顺序从Vector中取出测试方法。
3.避免编写有副作用的TestCase。
例如:
如果随后的测试依赖于某些特定的交易数据,就不要提交交易数据。
简单的会滚就可以了。
4.当继承一个测试类时,记得调用父类的setUp()和tearDown()方法。
5.将测试代码和工作代码放在一起,一边同步编译和更新。
(使用Ant中有支持junit的task.)
6.测试类和测试方法应该有一致的命名方案。
如在工作类名前加上test从而形成测试类名。
7.确保测试与时间无关,不要依赖使用过期的数据进行测试。
导致在随后的维护过程中很难重现测试。
8.如果你编写的软件面向国际市场,编写测试时要考虑国际化的因素。
不要仅用母语的Locale进行测试。
9.尽可能地利用JUnit提供地assert/fail方法以及异常处理的方法,可以使代码更为简洁。
10.测试要尽可能地小,执行速度快。
Junit使用简明手册
在使用XP进行开发的过程,unittest是必不可少的环节。
作为unittest,junit是首选的工具。
本文从使用目的、如何使用、以及使用中需要考虑的问题,简略描述了junit的基本用法。
使用目的
junit是java中书写unittest的framework,目前一些流行的unittest工具大都都是在junit上扩展而来的。
目前它的版本是junit3.8.1,可以从www.junit.org上下载。
用法
1. 基本使用步骤,Junit的使用非常简单,它的基本使用步骤:
- 创建,从junit.framework.TestCase派生unittest需要的testcase
- 书写测试方法,提供类似于如下函数签名的测试方法:
publicvoidtestXXXXX();
- 编译,书写完testcase后,编译所写的testcase类
- 运行,启动junittestrunner,来运行这个testcase。
Junit提供了2个基本的testrunner:
字符界面和图形界面。
启动命令分别如下:
a图形界面:
javajunit.swingui.TestRunnerXXXXX
b字符界面:
javajunit.textui.TestRunnerXXXXX
2. 使用例子:
importjunit.frmework.TestCase;
publicclassTestSampleextendsTestCaset{
publicvoidtestMethod1(){
assertTrue(true);
}
}
3. setUp与tearDown,这两个函数是junitframework中提供初始化和反初始化每个测试方法的。
setUp在每个测试方法调用前被调用,负责初始化测试方法所需要的测试环境;tearDown在每个测试方法被调用之后被调用,负责撤销测试环境。
它们与测试方法的关系可以描述如下:
测试开始->setUp->testXXXX->tearDown->测试结束
4. 使用例子:
importjunit.frmework.TestCase;
publicclassTestSampleextendsTestCaset{
protectedvoidsetUp(){
//初始化……
}
publicvoidtestMethod1(){
assertTrue(true);
}
potectedvoidtearDown(){
//撤销初始化……
}
}
5. 区分fail、exception。
- fail,期望出现的错误。
产生原因:
assert函数出错(如assertFalse(true));fail函数产生(如fail(……))。
- exception,不期望出现的错误,属于unittest程序运行时抛出的异常。
它和普通代码运行过程中抛出的runtime异常属于一种类型。
对于assert、fail等函数请参见junit的javadoc。
6. 使用例子:
importjunit.frmework.TestCase;
publicclassTestSampleextendsTestCaset{
protectedvoidsetUp(){
//初始化……
}
publicvoidtestMethod1(){
……
try{
booleanb=……
assertTrue(b);
thrownewException(“Thisisatest.”);
fail(“Unablepoint.”);//不可能到达
}catch(Exceptione){
fail(“Yes,Icatchu”);//应该到达点
}
……
}
potectedvoidtearDown(){
//撤销初始化……
}
}
7. 组装TestSuite,运行更多的test。
在junit中,Test、TestCase和TestSuite三者组成了composistepattern。
通过组装自己的TestSuite,可以完成对添加到这个TestSuite中的所有的TestCase的调用。
而且这些定义的TestSuite还可以组装成更大的TestSuite,这样同时也方便了对于不断增加的TestCase的管理和维护。
它的另一个好处就是,可以从这个TestCase树的任意一个节点(TestSuite或TestCase)开始调用,来完成这个节点以下的所有TestCase的调用。
提高了unittest的灵活性。
8. 使用例子:
importjunit.framework.Test;
importjunit.framework.TestSuite;
publicclassTestAll{
publicclassTestAll{
//定义一个suite,对于junit的作用可以视为类似于java应用程序的main。
publicstaticTestsuite(){
TestSuitesuite=newTestSuite("Runningalltests.");
suite.addTestSuite(TestCase1.class);
suite.addTestSuite(TestCase2.class);
returnsuite;
}
}
运行同运行单独的一个TestCase是一样的,参见step1“运行”。
9. 使用Antjunittask。
我们除了使用java来直接运行junit之外,我们还可以使用junit提供的junittask与ant结合来运行。
涉及的几个主要的anttask如下:
-
-
-
-
-
-
具体的语法请参见相关文档。
10. 使用例子:
检查表
junit的使用并不很难,然而要书写一个好的TestCase却并非易事。
一个不好的TestCase往往是既浪费了时间,也起不了实际的作用。
相反,一个好的TestCase,不仅可以很好的指出代码中存在的问题,而且也可以作为代码更准确的文档,同时还在持续集成的过程中起非常重要的作用。
在此给出书写TestCase时需要注意的几点:
- 测试的独立性:
一次只测试一个对象,方便定位出错的位置。
这有2层意思:
一个TestCase,只测试一个对象;一个TestMethod,只测试这个对象中的一个方法。
- 给测试方法一个合适的名字。
- 在assert函数中给出失败的原因,如:
assertTrue(“…shouldbetrue”,……),方便查错。
在这个例子中,如果无法通过assertTrue,那么给出的消息将被显示。
在junit中每个assert函数都有第一个参数是出错时显示消息的函数原型。
- 测试所有可能引起失败的地方,如:
一个类中频繁改动的函数。
对于那些仅仅只含有getter/setter的类,如果是由IDE(如Eclipse)产生的,则可不测;如果是人工写,那么最好测试一下。
- 在setUp和tearDown中的代码不应该是与测试方法相关的,而应该是全局相关的。
如针对与测试方法A和B,在setUp和tearDown中的代码应该是A和B都需要的代码。
- 测试代码的组织:
相同的包,不同的目录。
这样,测试代码可以访问被测试类的protected变量/方法,方便测试代码的编写。
放在不同的目录,则方便了测试代码的管理以及代码的打包和发布。
一个例子如下:
src<=源代码根目录
|---com
|---mod1
|---class1
junit<=测试代码根目录
|---com
|---mod1
|---class1
JUnit 4快速入门
JUnit4是JUnit框架有史以来的最大改进,其主要目标便是利用Java5的Annotation特性简化测试用例的编写。
让我们看看如何使用JUnit4来进行Unit测试。
请注意:
本文主要介绍JUnit4的最新特性和用法,并不会讲解Unit测试的基础。
如果你对JUnit框架还不熟悉,请先参考“在Eclipse中使用JUnit”一文,学习如何编写JUnit测试。
我们使用的开发环境是Eclipse3.2,它已经自带了JUnit4.1,你需要将JUnit4Library添加到项目用到的Library中。
另外,必须使用JDK5.0或更高版本。
要在Eclipse环境之外运行JUnit,需要下载JUnit4.1,具体请访问JUnit.org。
我们先看一个简单的Math类:
package com.crackj2ee.junit4;
public class Math {
public int abs(int value) {
return value>=0 ?
value :
(-value);
}
public int div(int a, int b) {
return a / b;
}
/**
* BUG:
if b less than 0!
*/
public float exp(int a, int b) {
float r = 1;
for(int i=0; i
r = r * a;
return r;
}
}
注意exp()方法是有Bug的,如果传入参数2,-1,则期待的返回值应为0.5F,但实际返回值为1.0F。
下面我们看看传统的JUnit的TestCase:
public class MathTest extends TestCase {
public void setUp() { super.setUp(); }
public void tearDown() { super.tearDown(); }
public void testAbs() { assertTrue(true); }
public void testDiv() {...}
public void testExp() {...}
}
JUnit依赖反射来执行每个以test开头的方法。
然而,在最新的JUnit4中,由于有了Annotation的支持,我们的测试方法不需要再以testXxx标识了,而是写上一个@Test标注即可。
例如:
@Test public void doAbs() {...}
甚至MathTest类也不必继承自TestCase。
你也许会想到,不继承自TestCase就无法调用assertXxx方法了,正因为如此,所有的assertXxx方法全部以静态方法被放入了Assert类,使用Assert.assertXxx()调用。
如果使用
import static org.junit.Assert.*;
则原有的代码不必改动。
setUp()和tearDown()方法也依赖@Before和@After标记,这样做的最大的好处是在继承体系内不必担心忘记了在setUp()方法中调用父类的super.setUp()方法,JUnit框架会自动处理父类的@Before和@After标记的方法。
并且,JUnit框架对@Before和@After的调用顺序类似于类的构造方法和析构方法,即@Before按照父类到子类的顺序调用,@After则相反,这样保证了资源的正确获取和释放。
当然,不再强迫必须使用setUp和tearDown作为方法名,可以使用更有意义的方法名,例如:
initDatabase()和closeDatabase(),只要它们被标注了@Before和@After即可。
来看看使用Annotation的MathTest:
package com.crackj2ee.junit4;
import static org.junit.Assert.*;
import org.junit.*;
public class MathTest {
public MathTest() {
System.out.println("new MathTest instance.");
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Junit 使用 简明 手册