首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

junit初始学习

2012-12-28 
junit初步学习开发过程中进行单元测试,尽可能尽早的将BUG找出,是开发者应该做的。JUNIT为JAVA开发者提供了

junit初步学习
开发过程中进行单元测试,尽可能尽早的将BUG找出,是开发者应该做的。JUNIT为JAVA开发者提供了一个很好的测试机制,以下是一个简单的JUNIT应用实例,也是初学可供参考的JUNIT模板。

java 代码

package junit.sineat.templet;???
import java.util.Hashtable;???
import junit.framework.Assert;???
import junit.framework.TestCase;???
import junit.framework.TestSuite;???
??
public class JunitB extends TestCase{???
??? /**定义你需要测试的类及用到的变量*****************************/??
??? public Hashtable hasha=null;//???
??? public Hashtable hashb=null;???
??? /*******************************************************/??????
??? public JunitB(String name){????????
??????? super(name);//创建子类?????????
??? }???
??? /**用setUp进行初始化操作*/??
??? protected void setUp() throws Exception {???
??????? super.setUp();???
??????? hasha =new Hashtable();//这里????
??? }???
??? /**用tearDown来销毁所占用的资源*/??
??? protected void tearDown() throws Exception {???
??????? super.tearDown();???
??????? //System.gc();???
??? }???
??? /**写一个测试方法断言期望的结果**/??
??? public void testBodyStatus() {?????
??????? //hasha =new Hashtable();//有此句后也可去掉setUp() tearDown()???
??????? assertNotNull(hasha);??????????
??????? //hasha.put("0","let's try again");//test1.error版???
??????? assertTrue(hasha.isEmpty());//期望为空?????????
??? }???
??? /**再写一个测试方法断言期望的结果**/??
??? public void testBodySame() {???????????
??????? //hashb=(Hashtable)hasha.clone();?? //test2.error版???
??????? hashb=hasha;??????????????????????? //test2.OK 版???
??????? Assert.assertSame(hasha,hashb);????????
??? }???
??? /**suite()方法,使用反射动态的创建一个包含所有的testXxxx方法的测试套件**/??
??? public static TestSuite suite()? {???
??????? return new TestSuite(JunitB.class);???
??? }???
??? /****写一个main()运行测试*****************/??
??? public static void main(String args[]) {???
??????? junit.textui.TestRunner.run(suite());//以文本运行器的方式方便的????????
??????? //junit.swingui.TestRunner.run(JunitB.class);???
??? }???
}???
??????? 以上为JUNIT的简单测试样例,不需过多考虑性能及规范,但资深JAVA开发者建议:
一、不要在测试用例的构造函数中做初始化
??? 答案是重载测试用例的setUp()方法进行初始化。
二、不要假定测试用例中测试的执行次序
??? 好的习惯是保持测试之间的独立性,使得它们在任何次序下执行的结果都是相同的。
三、测试要避免人工干预
??? 经验二讲的是不同的测试要避免相关性,而经验三讲的其实就是测试要避免自相关。
四、在子类中调用父类的setUp() 和tearDown()
五、不要硬性规定数据文件的路径
六、把测试的代码和被测的代码放在同样的目录下
七、正确命名测试
八、书写测试时要考虑地区和国家设置
九、利用Junit 的自动异常处理书写简洁的测试代码
???? 事实上在Junit 中使用try-catch 来捕获异常是没有必要的,Junit 会自动捕获异常。那些没有被捕获的异常就被当成错误处理。
十、充分利用Junit 的assert/fail 方法
???? assertSame()用来测试两个引用是否指向同一个对象
???? assertEquals()用来测试两个对象是否相等
十一、确保测试代码与时间无关
十二、使用文档生成器做测试文档。



异常:
public void testDivide2(){
??????? Throwable tx = null;
??????? try{
??????????? Calculator cal = new Calculator();
??????????? cal.divide(4, 0);
????????????
??????????? Assert.fail();
??????? }catch(Exception ex){
??????????? tx = ex;
??????? }
??????? System.out.println(tx.getMessage());
??????? Assert.assertNotNull(tx);
??????? Assert.assertEquals(Exception.class, tx.getClass());
??????? Assert.assertEquals("除数不能为零!!",tx.getMessage());
??? }
}


语法:
1. assertEquals([String message], expected,actual)

比较两个基本类型或对象是否相等(expected和actual是原始类型数值(primitive value)或者必须为实现比较而具有equal方法);

2.assertFalse([String message],boolean condition)

对布尔值求值,看它是否为“真“;

3.assertTrue([String message],boolean condition)

对布尔值求值,看它是否为“假“;

4.assertNull([String message],java.lang.Object object)

检查对象是否为“空“;

5.assertNotNull([String message],java.lang.Object object)

检查对象是否不为“空”;

6.assertSame([String message],expected,actual)

检查两个对象是否为同一实例;

7.assertNotSame([String message],expected,actual)

检查两个对象是否不为同一实例;

8. fail( String message )

使测试立即失败,其中 message 参数使可选的。这种断言通常被用于标记某个不应该到达的分支(例如,在一个预期发生的异常之后) 。


经验:
事实上在Junit 中使用try-catch 来捕获异常是没有必要的,Junit 会自动捕获异常。那些没有被捕获的异常就被当成错误处理。

在子类中调用父类的setUp() 和tearDown()


新特性:
JUnit依赖反射来执行每个以test开头的方法。然而,在最新的JUnit 4中,由于有了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:

ActionScript/Java代码
package com.crackj2ee.junit4;??
??
import static org.junit.Assert.*;??
??
import org.junit.*;??
??
public class MathTest??
{??
??
??? public MathTest()??
??? {??
??????? System.out.println("new MathTest instance.");??
??? }??
??
??? @Before public void setUp()throws Exception??
??? {??
??????? System.out.println("call @Before before a test method");??
??? }??
??
??? @After public void tearDown()throws Exception??
??? {??
??????? System.out.println("call @After after a test method");??
??? }??
??
??? @Test public void doAbs()??
??? {??
??????? Math math = new Math();??
??????? assertEquals(200, math.abs(200));??
??????? assertEquals(100, math.abs( - 100));??
??????? assertEquals(0, math.abs(0));??
??? }??
??
??? @Test public void doDiv()??
??? {??
??????? Math math = new Math();??
??????? assertEquals(5, math.div(100, 20));??
??????? assertEquals(4, math.div(100, 21));??
??? }??
??
??? @Test(expected = ArithmeticException.class)public void doDiv0()??
??? {??
??????? new Math().div(127, 0);??
??? }??
??
??? @Test(timeout = 1)public void doLongTimeTask()??
??? {??
??????? double d = 0;??
??????? for (int i = 1; i < 10000000; i++)??
??????????? d += i;??
??? }??
??
??? @Test public void testExp()??
??? {??
??????? Math math = new Math();??
??????? assertEquals(32f, math.exp(2, 5), 0.001f);??
??????? assertEquals(1f, math.exp(2, 0), 0.001f);??
??????? assertEquals(0.5f, math.exp(2, ( - 1)), 0.001f);??
??? }??
??
}??

对测试异常,JUnit 4可以用expected=Exception.class来期待一个预期的异常,而不必编写

ActionScript/Java代码
try {??
??? ...??
??? fail("No exception");??
}??
??? catch(Exception e) {??
??? // OK!??
}??

来看看doDiv0测试,我们期待一个除数为0的ArithmeticException,因此编写如下测试方法:

ActionScript/Java代码
@Test(expected=ArithmeticException.class)??
public void doDiv0() {??
?? new Math().div(127, 0);??
}??

对于非常耗时的测试,@Test还有一个timeout来标识该方法最长执行时间,超过此时间即表示该测试方法失败:

ActionScript/Java代码
@Test(timeout=1)??
public void doLongTimeTask() {??
?? double d = 0;??
?? for(int i=1; i<10000000; i++)??
????? d+=i;??
}??

以上方法若执行时间超过1ms则测试失败,由于依赖CPU的执行速度,在不同的机器上测试结果也不同。

JUnit 4另一个较大的变化是引入了@BeforeClass和@AfterClass,它们在一个Test类的所有测试方法执行前后各执行一次。这是为了能在 @BeforeClass中初始化一些昂贵的资源,例如数据库连接,然后执行所有的测试方法,最后在@AfterClass中释放资源。

正如你能想到的,由于@BeforeClass和@AfterClass仅执行一次,因此它们只能标记静态方法,在所有测试方法中 共享的资源也必须是静态引用:

ActionScript/Java代码
private static Object dbConnection;??
??
@BeforeClass??
public static void setUpBeforeClass() throws Exception {??
?? System.out.println("call @BeforeClass and init database connection");??
?? dbConnection = new Object();??
}??
??
@AfterClass??
public static void tearDownAfterClass() throws Exception {??
?? System.out.println("call @AfterClass to release database connection");??
?? dbConnection = null;??
}??

最后执行测试用例,可以看到结果:

各个方法执行顺序如下:

call @BeforeClass and init database connection

new MathTest instance.
call @Before before a test method
call @After after a test method

new MathTest instance.
call @Before before a test method
call @After after a test method

...

call @AfterClass to release database connection

可以看到,@BeforeClass是在实例化MathTest之前调用的,因此不能在构造方法中初始化共享资源。

最后需要注意的是由于Java 5的自动Box/Unbox特性,在调用assertEquals()时要特别注意,如果你传入:

assertEquals(100F, 100);

则按照自动Box变为:

assertEquals(new Float(100F), new Integer(100));

测试失败,因为Float类和Integer类不是同一类型。

因此要特别注意float和double的测试。事实上对float和double应使用

assertEquals(float, float, float delta);
assertEquals(double, double, double delta);

delta指定了两个作比较的浮点数的相差范围,在此范围内的两个浮点数将认为相等。可以传入一个很小的数例如0.0001F。

JUnit 4非常适合使用Java 5的开发人员,但是无法在Java 1.4中获得这些好处,并且,也不与以前的版本兼容。因此,如果你正在使用Java 5,就可以考虑使用JUnit 4来编写测试。

异常2:
try{

??????????????????????????? boolean b= ……

??????????????????????????? assertTrue( b);

??????????????????????????? throw new Exception( “This is a test.”);

??????????????????????????? fail( “Unable point.”);???? //不可能到达

???????????????????? }catch(Exception e){

??????????????????????????? fail( “Yes, I catch u”); //应该到达点
}


学习连接:
http://zengbo0710.iteye.com/blog/79373

http://pharaohsprince.iteye.com/blog/74907

http://zhangwenjun8045.iteye.com/blog/159095

http://dang.iteye.com/blog/182612

http://fengyouhua.iteye.com/blog/92365

热点排行