JUnit3.8使用简介

本文转自http://87nba87.iteye.com/blog/665821

JUnit是*Unit家族的第一产品,一直被广泛应用。他是Kent Beck和Erich Gamma两位大师的作品(GOF中的两人,设计模式那本书是4个人写的,这两个是其中两位)。目前已经成为Java领域单元测试默认的标准。 

现在的版本是4.*,由于4的版本基于了JDK5以上,利用了大量的Annotation,是测试变的更加方便。 
不过本文还是介绍JUnit3.8是如何使用的。关于4的介绍,接下来会马上跟进。 
当然JUnit是非常简单,但是做单元测试绰绰有余。 
首先先了解一下JUnit的目的。 
我们利用JUnit进行单元测试,目的就是发现我们代码中可能存在的问题,当然我们的单元测试不可能发现所有的问题,但是确可以保证我们已知的功能,和我们可以考虑到的功能进行测试。 

我们先来一个类,然后根据这个类编写相关的测试用例,将JUnit3.8关键知识点列出。 
用户帐户类 
UserAccount.java 
/** 
* 用户帐户对象 
*/ 
public class UserAccount { 

private int money; 

public UserAccount(){ 
   money=0; 

/** 
* 存钱 
*/ 
public void depositeMoney(int i){ 
   money+=i; 

/** 
* 取钱 
*/ 
public void withdrawMoney(int i){ 
   money-=i; 

/** 
* 查看帐户 
*/ 
public int showMoney(){ 
   return money; 




这个就是我们带测试的一个类,实际状况肯定比这个要复杂的多,这个例子仅仅是引出JUnit,看JUnit如何使用,因为具体的测试用例是相关人员自己构建的。 
1:构建TestCase类 
public class UserAccountTest extends TestCase{ 

测试用例类必须实现TestCase,命名习惯一般是在待测试类名称后面加上Test。 

2:构建测试方法 
可以自动执行的测试方法必须满足如下几个条件 
1)必须是public 
2)无返回值void 
3)方法名称以test开始。(一般是在带测试方法前加上test) 
4)无任何参数 


/** 
* 测试存钱>0 
*/ 
public void testDepositeMoney(){ 
UserAccount account=new UserAccount(); 
account.depositeMoney(100); 
Assert.assertEquals(100, account.showMoney()); 

这里涉及到一个关键的类Assert(断言),断言就是一定是真的。不是真的就结束。 
运行一下,看见的是绿色。OK,只要是绿色一切都是正常的。 

接下来我们要测试一些用例: 
1)存入的钱小于0 
2)取出的钱小于0 
3)帐户没有钱,直接取 
4)帐户有钱,但是钱不够 
5)存入足够的钱,然后取出。 
6)存入50,取100,存入200,取50,存入30,存入10,取100,取200.在每次存取的时候设置断言。 

在我们要实现这些用例的时候我们发现了,我们写的UserAccount存在很多问题。 
用例1,2,3,4,这四种明显错误的操作,我们的程序竟然没有报任何的错误。 

/** 
* 存钱小于0 
*/ 
public void testDepositeMoney2(){ 
UserAccount account=new UserAccount(); 
account.depositeMoney(-100); 


/** 
* 取钱数目小于0 
*/ 
public void testWithdrawMoney(){ 
UserAccount account=new UserAccount(); 
account.withdrawMoney(-100); 

/** 
* 帐户没有钱,取钱 
*/ 
public void testWithdrawMoney2(){ 
UserAccount account=new UserAccount(); 
account.withdrawMoney(100); 


/** 
* 先存钱,在取钱,依然余额不足 
*/ 
public void testWithdrawMoney3(){ 
UserAccount account=new UserAccount(); 
account.depositeMoney(50); 
account.withdrawMoney(100); 

以上四个方法,如果我们都调用showMeney的方法会发现,帐户的余额肯定存在小于0的情况,这是明显不对的,我们需要将我们的UserAccount的bug进行修改。 

/** 
* 用户帐户对象 
*/ 
public class UserAccount { 

private int money; 

public UserAccount(){ 
   money=0; 

/** 
* 存钱 
* @param i 
*/ 
public void depositeMoney(int i) throws Exception{ 
   if(i<0) 
    throw new Exception("存钱数目必须大于0.");  
   money+=i; 

/** 
* 取钱 
* @param i 
* @return 
*/ 
public void withdrawMoney(int i) throws Exception{ 
   if(i<0) 
    throw new Exception("取钱数目必须大于0."); 
   if(money<i) 
    throw new Exception("帐户余额不足."); 
   money-=i; 

/** 
* 查看帐户 
* @return 
*/ 
public int showMoney(){ 
   return money; 



在完善我们的测试用例之前,还需要将setUp和tearDown这两个方法引入进来。 
setUp()这个方法是JUnit默认执行的,就是当调用测试方法之前要先运行这个方法。 
当测试方法运行结束的时候要运行另一个方法tearDown(). 

Assert.fail(); 
这个方法在我们的测试用例中大量出现,这个方法的意思就是,当成与运行这条语句的时候结束所有的断言。 

完整的测试类: 
UserAccountTest.java 

public class UserAccountTest extends TestCase{ 

private UserAccount account; 
/** 
* 任何一个测试方法执行前,必然运行的方法 
*/ 
protected void setUp(){ 
   account=new UserAccount(); 

/** 
* 任何一个测试方法执行后,必然运行的方法 
*/ 
protected void tearDown(){ 
  

/** 
* 测试存钱>0 
*/ 
public void testDepositeMoney(){ 
   try { 
    account.depositeMoney(100); 
   } catch (Exception e) { 
    Assert.fail(); 
   } 
   Assert.assertEquals(100, account.showMoney()); 

/** 
* 测试存钱小于0 
*/ 
public void testDepositeMoney2(){ 
   try { 
    account.depositeMoney(-100); 
    Assert.fail(); 
   } catch (Exception e) { 
    Assert.assertEquals("存钱数目必须大于0.", e.getMessage()); 
   } 

/** 
* 测试取钱数目小于0 
*/ 
public void testWithdrawMoney(){ 
   try { 
    account.withdrawMoney(-100); 
    Assert.fail(); 
   } catch (Exception e) { 
    Assert.assertEquals("取钱数目必须大于0.", e.getMessage()); 
   } 

/** 
* 测试帐户没有钱,取钱 
*/ 
public void testWithdrawMoney2(){ 
   try { 
   
    account.withdrawMoney(100); 
    Assert.fail(); 
   } catch (Exception e) { 
    Assert.assertEquals("帐户余额不足.", e.getMessage()); 
   } 

/** 
* 先存钱,在取钱,依然余额不足 
*/ 
public void testWithdrawMoney3(){ 
   try { 
    account.depositeMoney(50); 
    account.withdrawMoney(100); 
    Assert.fail(); 
   } catch (Exception e) { 
    Assert.assertEquals("帐户余额不足.", e.getMessage()); 
   } 

/** 
* 先存钱,在取钱 
*/ 
public void testWithdrawMoney4(){ 
   try { 
    account.depositeMoney(200); 
    account.withdrawMoney(100); 
    Assert.assertEquals(100, account.showMoney()); 
   } catch (Exception e) { 
    e.printStackTrace(); 
    Assert.fail(); 
   } 

/** 
* 测试混合方法 
* 存入50,取100,存入200,取50,存入30,存入10,取100,取200.在每次存取的时候设置断言。 
*/ 
public void testComplex(){ 
   try{ 
    account.depositeMoney(50); 
    Assert.assertEquals(50,account.showMoney()); 
   } 
   catch (Exception e) { 
    Assert.fail(); 
   } 
  
   try{ 
    account.withdrawMoney(100); 
    Assert.fail(); 
   } 
   catch (Exception e) { 
    Assert.assertEquals("帐户余额不足.", e.getMessage()); 
   } 
  
   try{ 
    account.depositeMoney(200); 
    Assert.assertEquals(250,account.showMoney()); 
   } 
   catch (Exception e) { 
    Assert.fail(); 
   } 
  
   try{ 
    account.withdrawMoney(50); 
    Assert.assertEquals(200,account.showMoney()); 
   } 
   catch (Exception e) { 
    Assert.fail(); 
   } 
  
   try{ 
    account.depositeMoney(30); 
    Assert.assertEquals(230,account.showMoney()); 
   }  
   catch (Exception e) { 
    Assert.fail(); 
   } 
  
   try{ 
    account.depositeMoney(10); 
    Assert.assertEquals(240,account.showMoney()); 
   } 
   catch (Exception e) { 
    Assert.fail(); 
   } 
  
   try{ 
    account.withdrawMoney(100); 
    Assert.assertEquals(140,account.showMoney()); 
   } 
   catch (Exception e) { 
    Assert.fail(); 
   } 
  
   try{ 
    account.withdrawMoney(200); 
    Assert.fail(); 
   } 
   catch (Exception e) { 
    Assert.assertEquals("帐户余额不足.", e.getMessage()); 
   } 
   Assert.assertEquals(140, account.showMoney()); 



这样JUnit的单元测试的方法,和测试基本关键点已经描述,主要还需要在实际的工作中体会使用。 


三种测试环境: 

接下来是介绍JUnit可以有三种自定义的环境下运行JUnit的测试。 
Text,AWT,Swing。 
在main方法中运行如下三段代码。 
junit.awtui.TestRunner.run(UserAccountTest.class); 

junit.swingui.TestRunner.run(UserAccountTest.class); 

junit.textui.TestRunner.run(UserAccountTest.class); 

会弹出两个窗口,同时在控制台有信息打出。 
弹出的两个窗口是JUnit自带的AWT和Swing两种显示环境。 
控制台是Text显示环境。 

以上是通过main方法来运行三种测试环境。 
还可以通过java命令的方式。 
java junit.textui.TestRunner com.test.UserAccountTest 
这种方式也适合以上三种环境。 


如何测试工程中所有的测试用例: 
我们的项目会有很多测试用例,测试用例是同代码基本上同步,当项目基本完成,我们希望运行一下全部的测试用例,这个时候怎么办呢,不可能一个个运行。 
实际上JUnit已经提供了这种测试的方法。而且用到了Composite的设计模式,主要是作者太强。 
我们看看如何实现的。 
public class TestAll extends TestCase{ 

public static Test suite(){ 
   TestSuite test=new TestSuite(); 
   test.addTestSuite(UserAccountTest.class); 
   test.addTestSuite(UserDaoTest.class); 
   。。。。。 
   return test; 


这个TestAll也是需要继承TestCase. 
定义suite的方法必须按照这种方式定义。 
public static Test suite() 

注:TestCase实现了Test接口,TestSuite实现了Test接口。 

TestSuite是一个动态Test的合成类(Composite),可以运行一个Test集合。 

Failure和Error 

在JUnit中当运行结果可能出现问题,这个问题分为两种情况,一种是Error一种是Failure。 

Error:执行断言之前就已经发生的异常,是由于程序本身的的错误,导致运行的异常,而非由于断言的错误。 

Failure:执行断言异常,实际运行与预期运行结果不同导致,应该是由于测试程序运行中出现的错误。 

可以理解为Error是本身程序错误,Failure是由于测试程序错误。 


基本上JUnit3.8版本的知识点就这些了,缺少的可能是同ant的整合,这个有时间会补充上来。 

接下来会将JUnit4的使用方法发出来。 

你可能感兴趣的:(JUnit3.8使用简介)