junit3与junit4的区别.docx

上传人:b****8 文档编号:10664202 上传时间:2023-02-22 格式:DOCX 页数:12 大小:22.14KB
下载 相关 举报
junit3与junit4的区别.docx_第1页
第1页 / 共12页
junit3与junit4的区别.docx_第2页
第2页 / 共12页
junit3与junit4的区别.docx_第3页
第3页 / 共12页
junit3与junit4的区别.docx_第4页
第4页 / 共12页
junit3与junit4的区别.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

junit3与junit4的区别.docx

《junit3与junit4的区别.docx》由会员分享,可在线阅读,更多相关《junit3与junit4的区别.docx(12页珍藏版)》请在冰豆网上搜索。

junit3与junit4的区别.docx

junit3与junit4的区别

JUnit4的新特征

一、引言

在本文开始,我将假定,你已经了解由KentBeck和ErichGamma发明的这个Java单元测试框架并因此而略过必要的简介。

所以,我将集中分析从JUnit3.8到最新版本JUnit4的迁移过程以及其在IDE和Ant中的集成。

JUnit4是一种与其之前的版本完全不同的API,它根据Java5.0中的新特征(注解,静态导入等)构建而成。

如你所见,JUnit4更简单、更丰富和更易于使用,而且它引入了更为灵活的初始化和清理工作,还有限时的和参数化测试用例。

代码实例最能说明问题。

因此,在本文中,我将使用一个例子来展示不同的测试用例:

一个计算器。

该示例计算器很简单,效率并不高,甚至还有一些错误;它仅仅操作整数,并且把结果存储在一个静态变量中。

Substract方法并不返回一个有效的结果,而且也没有实现乘法运算,而且看上去在squareRoot方法中还存在一个错误:

无限循环。

这些错误将帮助说明使用JUnit4进行测试的有效性。

你可以打开和关闭这个计算器,而且你可以清除这些结果。

下面是其实现代码:

packagecalc;

publicclassCalculator{

 privatestaticintresult;//存储结果的静态变量

 publicvoidadd(intn){

  result=result+n;

 }

 publicvoidsubstract(intn){

  result=result-1;//错误:

应该是"result=result-n"

 }

 publicvoidmultiply(intn){}//还没实现

 publicvoiddivide(intn){

  result=result/n;

 }

 publicvoidsquare(intn){

  result=n*n;

 }

 publicvoidsquareRoot(intn){

  for(;;);//错误:

无限循环

 }

 publicvoidclear(){//清除结果

  result=0;

 }

 publicvoidswitchOn(){//打开屏幕,显示"hello",并报警

  result=0;//实现其它的计算器功能

 }

 publicvoidswitchOff(){}//显示"byebye",报警,并关闭屏幕

 publicintgetResult(){

  returnresult;

 }

}

二、迁移一个测试类

现在,我将把一个已经使用JUnit3.8编写成的简单的测试类迁移到JUnit4。

这个类有一些缺陷:

它没有测试所有的业务方法,而且看上去在testDivide方法中还存在一个错误(8/2不等于5)。

因为还没有实现乘法运算功能,所以对其测试将被忽略。

下面,我们把两个版本的框架之间的差别以粗体显示出现于表格1中。

表格1.分别以JUnit3.8和JUnit4实现的CaculatorTest。

JUnit3.8

packagejunit3;

importcalc.Calculator;

importjunit.Framework.TestCase;

publicclassCalculatorTestextendsTestCase{

 privatestaticCalculatorcalculator=newCalculator();

 @OverrideprotectedvoidsetUp(){calculator.clear();}

 publicvoidtestAdd(){

  calculator.add

(1);

  calculator.add

(1);

  assertEquals(calculator.getResult(),2);

 }

 publicvoidtestSubtract(){

  calculator.add(10);

  calculator.subtract

(2);

  assertEquals(calculator.getResult(),8);

 }

 publicvoidtestDivide(){

  calculator.add(8);

  calculator.divide

(2);

  assertcalculator.getResult()==5;

 }

 publicvoidtestDivideByZero(){

  try{

   calculator.divide(0);

   fail();

  }

  catch(ArithmeticExceptione){}

 }

 publicvoidnotReadyYetTestMultiply(){

  calculator.add(10);

  calculator.multiply(10);

  assertEquals(calculator.getResult(),100);

 }

}

JUnit4

packageJUnit4;

importcalc.Calculator;

importorg.junit.Before;

importorg.junit.Ignore;

importorg.junit.Test;

importstaticorg.junit.Assert.*;

publicclassCalculatorTest{

 privatestaticCalculatorcalculator=newCalculator();

 @BeforepublicvoidclearCalculator(){

  calculator.clear();

 }

 @Testpublicvoidadd(){

  calculator.add

(1);

  calculator.add

(1);

  assertEquals(calculator.getResult(),2);

 }

 @Testpublicvoidsubtract(){

  calculator.add(10);

  calculator.subtract

(2);

  assertEquals(calculator.getResult(),8);

 }

 @Testpublicvoiddivide(){

  calculator.add(8);

  calculator.divide

(2);

  assertcalculator.getResult()==5;

 }

 @Test(expected=ArithmeticException.class)

 publicvoiddivideByZero(){

  calculator.divide(0);

 }

 @Ignore("notreadyyet")

 @Test

 publicvoidmultiply(){

  calculator.add(10);

  calculator.multiply(10);

  assertEquals(calculator.getResult(),100);

 }

}

#p#

三、包

首先,你可以看到,JUnit4使用org.junit.*包而JUnit3.8使用的是junit.Framework.*。

当然,为了向后兼容性起见,JUnit4jar文件发行中加入了这两种包。

四、继承

在中,测试类不必再扩展junit.framework.TestCase;事实上,它们不必须扩展任何内容。

但是,JUnit4中使用的是注解。

为了以一个测试用例方式执行,一个JUnit4类中至少需要一个@Test注解。

例如,如果你仅使用@Before和@After注解而没有至少提供一个@Test方法来编写一个类,那么,当你试图执行它时将得到一个错误:

Java.lang.Exception:

Norunnablemethods.

五、断言(Assert)方法

因为在JUnit4中一个测试类并不继承自TestCase(在JUnit3.8中,这个类中定义了assertEquals()方法),所以你必须使用前缀语法(举例来说,Assert.assertEquals())或者(由于JDK5.0)静态地导入Assert类。

这样以来,你就可以完全象以前一样使用assertEquals方法(举例来说,assertEquals())。

另外,在JUnit4中,还引入了两个新的断言方法,它们专门用于数组对象的比较。

如果两个数组包含的元素都相等,那么这两个数组就是相等的。

publicstaticvoidassertEquals(Stringmessage,Object[]expecteds,Object[]actuals);

publicstaticvoidassertEquals(Object[]expecteds,Object[]actuals);

由于JDK5.0的自动装箱机制的出现,原先的12个assertEquals方法全部去掉了。

例如,原先JUnit3.8中的assertEquals(long,long)方法在JUnit4中要使用assertEquals(Object,Object)。

对于assertEquals(byte,byte)、assertEquals(int,int)等也是这样。

这种改进将有助于避免反模式。

在JUnit4中,新集成了一个assert关键字(见我们的例子中的divide()方法)。

你可以象使用assertEquals方法一样来使用它,因为它们都抛出相同的异常(java.lang.AssertionError)。

JUnit3.8的assertEquals将抛出一个junit.framework.AssertionFailedError。

注意,当使用assert时,你必须指定Java的"-ea"参数;否则,断言将被忽略。

六、预设环境(Fixture)

Fixture是在测试期间初始化和释放任何普通对象的方法。

在JUnit3.8中,你要使用setUp()来实现运行每一个测试前的初始化工作,然后使用tearDown()来进行每个测试后的清理。

这两个方法在TestCase类中都得到重载,因此都被唯一定义。

注意,我在这个Setup方法使用的是Java5.0内置的@Override注解-这个注解指示该方法声明要重载在超类中的方法声明。

在JUnit4中,则代之使用的是@Before和@After注解;而且,可以以任何命名(在我们的例子中是clearCalculator())来调用这些方法。

在本文后面,我将更多地解释这些注解。

七、测试

JUnit3.8通过分析它的签名来识别一个测试方法:

方法名必须以“test”为前缀,它必须返回void,而且它必须没有任何参数(举例来说,publicvoidtestDivide())。

一个不遵循这个命名约定的测试方法将被框架简单地忽略,而且不抛出任何异常(指示发生了一个错误)。

JUnit4不使用与JUnit3.8相同的约定。

一个测试方法不必以'test'为前缀,但是要使用@Test注解。

但是,正如在前一个框架中一样,一个测试方法也必须返回void并且是无参数的。

在JUnit4中,可以在运行时刻控制这个要求,并且不符合要求的话会抛出一个异常:

java.lang.Exception:

Methodxxxshouldhavenoparameters

java.lang.Exception:

Methodxxxshouldbevoid

@Test注解支持可选参数。

它声明一个测试方法应该抛出一个异常。

如果它不抛出或者如果它抛出一个与事先声明的不同的异常,那么该测试失败。

在我们的例子中,一个整数被零除应该引发一个ArithmeticException异常。

八、忽略一个测试

记住,不能执行多个方法。

然而,如果你不想让测试失败的话,你可以仅仅忽略它。

那么,在JUnit3.8中,我们是如何实现临时禁止一个测试的呢?

方法是:

通过注释掉它或者改变命名约定,这样测试运行机就无法找到它。

在我的例子中,我使用了方法名notReadyYetTestMultiply()。

它没有以“test”开头,所以它不会被识别出来。

现在的问题是,在成百上千的测试中间,你可能记不住重命名这个方法。

#p#

在JUnit4中,为了忽略一个测试,你可以注释掉一个方法或者删除@Test注解(你不能再改变命名约定,否则将抛出一个异常)。

然而,该问题将保留:

该运行机将不报告这样一个测试。

现在,你可以把@Ignore注解添加到@Test的前面或者后面。

测试运行机将报告被忽略的测试的个数,以及运行的测试的数目和运行失败的测试数目。

注意,@Ignore使用一个可选参数(一个String),如果你想记录为什么一个测试被忽略的话。

九、运行测试

在JUnit3.8中,你可以选择使用若干运行机:

文本型,AWT或者Swing。

JUnit4仅仅使用文本测试运行机。

注意,JUnit4不会显示任何绿色条来通知你测试成功了。

如果你想看到任何类型的绿色的话,那么你可能需要使用JUnit扩展或一种集成了JUnit的IDE(例如IDEA或者Eclipse)。

首先,我想使用老式但好用的junit.textui.TestRunner来运行该JUnit3.8测试类(考虑到使用assert关键字,我使用了-ea参数)。

java-eajunit.textui.TestRunnerjunit3.CalculatorTest

..F.E.

Therewas1error:

1)testDivide(junit3.CalculatorTest)java.lang.AssertionError

atjunit3.CalculatorTest.testDivide(CalculatorTest.java:

33)

Therewas1failure:

1)testSubtract(junit3.CalculatorTest)junit.framework.AssertionFailedError:

expected:

<9>

butwas:

<8>

atjunit3.CalculatorTest.testSubtract(CalculatorTest.java:

27)

FAILURES!

!

!

Testsrun:

4,Failures:

1,Errors:

1

TestDivide产生一个错误,因为断言确定了8/2不等于5。

TestSubstract产生一个失败,因为10-2应该等于8,但是在这个实现中存在一个错误:

它返回9。

现在,我使用新的org.junit.runner.JUnitCore运行机来运行这两个类。

注意,它能执行JUnit4和JUnit3.8测试,甚至是这二者的结合。

java-eaorg.junit.runner.JUnitCorejunit3.CalculatorTest

JUnitversion4.1

..E.E.

Therewere2failures:

1)testSubtract(junit3.CalculatorTest)

junit.framework.AssertionFailedError:

expected:

<9>butwas:

<8>

atjunit.framework.Assert.fail(Assert.java:

47)

2)testDivide(junit3.CalculatorTest)

java.lang.AssertionError

atjunit3.CalculatorTest.testDivide(CalculatorTest.java:

33)

FAILURES!

!

!

Testsrun:

4,Failures:

2

***

java-eaorg.junit.runner.JUnitCoreJUnit4.CalculatorTest

JUnitversion4.1

...E.EI

Therewere2failures:

1)subtract(JUnit4.CalculatorTest)

java.lang.AssertionError:

expected:

<9>butwas:

<8>

atorg.junit.Assert.fail(Assert.java:

69)

2)divide(JUnit4.CalculatorTest)

java.lang.AssertionError

atJUnit4.CalculatorTest.divide(CalculatorTest.java:

40)

FAILURES!

!

!

Testsrun:

4,Failures:

2

第一个非常明显的区别是,JUnit版本号被显示于控制台中(4.1)。

第二个区别是,JUnit3.8区分失败和错误;JUnit4则仅使用失败进行简化。

一个新奇的地方是,字母“I”,它显示一个测试被忽略。

十、高级测试

现在,我将展示JUnit4的一些高级特征。

列表1(见下载源码)是一个新的测试类-AdvancedTest,它派生自AbstractParent。

(一)高级预设环境

两个类都使用新的注解@BeforeClass和@AfterClass,还有@Before和@After。

表格2展示了在这些注解之间的主要区别。

表格2.@BeforeClass/@AfterClass比较于@Before/@After。

@BeforeClass和@AfterClass

 

@Before和@After

在每个类中只有一个方法能被注解。

多个方法能被注解,但其执行的顺序未特别指定,且不运行重载方法。

方法名是不相关的。

方法名是不相关的。

每个类运行一次。

在每个测试方法运行前或运行后运行。

在当前类的@BeforeClass方法运行前先运行超类的@BeforeClass方法。

在超类中声明的@AfterClass方法将在所有当前类的该方法运行后才运行。

超类中的@Before在所有子类的该方法运行前运行。

在超类中的@After在在所有子类的该方法运行后才运行。

必须是公共和非静态的。

必须是公共和非静态的。

即使一个@BeforeClass方法抛出一个异常,所有的@AfterClass方法也保证被运行。

即使一个@Before或者@Test方法抛出一个异常,所有的@After方法也保证被运行。

如果你仅有一次需要分配和释放昂贵的资源,那么@BeforeClass和@AfterClass可能很有用。

在我们的例子中,AbstractParent使用这些在startTestSystem()和stopTestSystem()方法上的注解启动和停止整个测试系统。

并且它使用@Before和@After初始化和清除系统。

子类AdvancedTest也混合使用这些注解。

在你的测试代码中使用System.out.println不是一种良好的实践习惯;但是,在这个用例中,它有助于理解这些注解被调用的顺序。

当我运行AdvancedTest时,我得到如下结果:

Starttestsystem//父类的@BeforeClass

Switchoncalculator//子类的@BeforeClass

Initializetestsystem//第一个测试

Clearcalculator

Initializetestsystem//第二个测试

Clearcalculator

Cleantestsystem

Initializetestsystem//第三个测试

Clearcalculator

Cleantestsystem

Initializetestsystem//第四个测试

Clearcalculator

Cleantestsystem

Switchoffcalculator//子类的@AfterClass

Stoptestsystem//父类的@AfterClass

如你所见,@BeforeClass和@AfterClass仅被调用一次,而@Before和@Afterare在每次测试中都要调用。

(二)限时测试

在前面的例子中,我为squareRoot()方法编写了一个测试用例。

记住,在这个方法中存在一个错误-能够导致它无限循环。

如果没有结果的话,我想让这个测试在1秒钟后退出。

这一功能正是timeout参数所要实现的。

@Test注解的第二个可选参数(第一个参数是必需的)可以使一个测试失败,如果该测试花费比一个预先确定的时限(毫秒)还长的时间的话。

当我运行该测试时,我得到如下的运行结果:

Therewas1failure:

1)squareRoot(JUnit4.AdvancedTest)

Java.lang.Exception:

testtimedoutafter1000milliseconds

atorg.junit.internal.runners.TestMethodRunner.runWithTimeout(TestMethodRunner.java:

68)

atorg.junit.internal.runners.TestMethodRunner.运行(TestMethodRunner.java:

43)

FAILURES!

!

!

Testsrun:

4,Failures:

1

(三)参数化测试

在列表1中,我测试了squareRoot(它是square方法而不是squareRoot方法)-通过创建若干测试方法(square2,square4,square5),这些方法都完成相同的事情(通过被一些变量参数化实现)。

其实,现在这里的复制/粘贴技术可以通过使用一个参数化测试用例加以优化(列表2)。

在列表2(见本文相应下载源码)中的测试用例使用了两个新的注解。

当一个类被使用@RunWith注释时,JUnit将调用被参考的类来运行该测试而不是使用缺省的运行机。

为了使用一个参数化测试用例,你需要使用运行机org.junit.runners.Parameterized。

为了确定使用哪个参数,该测试用例需要一个公共静态方法(在此是data(),但是名字似乎无关),该方法返回一个Collection,并且被使用@参数加以注解。

你还需要一个使用这些参数的公共构造函数。

当运行这个类,该输出是:

javaorg.junit.runner.JUnitCoreJUnit4.SquareTest

JUnitversion4.1

.......E

Therewas1failure:

1)square[6](JUnit4.Squa

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育 > 政史地

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1