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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值