junit in java 真正的测试用例实战!

单元测试基础
         当今软件测试十分盛行时,本人通过项目实践和个人亲身体会浅谈单元测试,本人一直坚持 用代码说话的原则 ,同时也希望个人能给出宝贵意见,共同探讨、共同进步,为中国软件事业有更大的发展共同奋斗!
最早我们项目组开发的项目时,写代码都是从底层一直写到表现层到 jsp ,然后开发人员在 web 层调试页面,近乎 98 %都会报一大堆 exception, 然后再在代码中加断点一步一步查到底哪一层代码出现问题 ……, 比较好点做法就是在各个类中加上 main 方法测试,但总体很不理想,给 web 层开发人员的调试和质量控制人员带来繁重的工作压力;使用单元测试后,针对每一个方法都做严格的把关,大大减少调试的时间;同时质量控制人员返回过来的 bug 少了近 60 %,现在对于开发人员写测试用例非常熟练,并且本人根据实际情况对测试用例做了点小小改动(这部分主要在后面代码中详述),带来很好的效果!
单元测试到底给实际开发带来什么好处那?
(1) 首先对于开发人员来说大大减少调试工作的时间,同时也规范了对于代码安全管理(我们知道那些方法是可以调用的);
(2) 对于整个项目来说,有了完整的测试,保证项目最后交付测试有了可靠依据;
(3)对于测试人员大大减少bug的反馈;
(4)对于项目经理整个项目达到很好的可控;
(5)最主要的完整的单元测试给后期维护人员带来很大的便捷!

单元测试好处可能还有很多,但本人只能理解和感悟这么多 , 希望观者补充!
单元测试配置:
       我将使用 eclipse myEclopse 给大家介绍关于 JUNIT 的环境的简单配置;右键点击项目选择 属性 ,在弹出窗口中到环境变量中添加 junit.jar 包,这样下一步我们就可以进行单元测试了;
使用 eclipse 快速开发 test Case
如下图:右键选择你要测试的类,在新建中点击 “JUnit 测试用例
弹出对话框,配置测试名称和根目录,添加注释等,再点击 下一步 到下图:
      选择你要测试类中的方法,点击完成!便生成测试类的基本框架,如下代码,我们以对一个 DAO 类测试为例:
/*
 * Copyright reserved 2005 by XXXXCo. Ltd.
 * Author:XXX   Date:2006-9-4
 
*/


import  junit.framework.TestCase;

/**  
 * 
@author  XXX
 
*/
public   class  OrgTypeDAOTest  extends  TestCase {
    
/**  
     * 
@param  arg0
     
*/
    
public  OrgTypeDAOTest(String arg0){
        
super (arg0);
    }

    
/**  
     * 
@see  junit.framework.TestCase#setUp()
     
*/
    
protected   void  setUp()  throws  Exception{       

          
super .setUp();
    }

    
/**
     * 
@see  junit.framework.TestCase#tearDown()
     
*/
    
protected   void  tearDown()  throws  Exception{
        
super .tearDown();
    }
    
/**  
     *  主函数
     * 
@param  args
     
*/
    
public   static   void  main(String[] args){
        TestRunner.run(OrgTypeDAOTest .
class );
    }
    
/**  
     * {
@link  OrgTypeDAO#getOrgTypeList()} 的测试方法。
     
*/
    
public   final   void  testGetOrgTypeList() {
        fail(
" 尚未实现 " );  //  TODO
    }

    
/**  
     * {
@link  OrgTypeDAO#insertOrgTypeInfo(com.zhjy.mltx.vo.OrgTypeVO)} 的测试方法。
     
*/
    
public   final   void  testInsertOrgTypeInfo() {
        fail(
" 尚未实现 " );  //  TODO
    }

    
/**  
     * {
@link  OrgTypeDAO#deleteOrgTypeInfo(java.lang.String)} 的测试方法。
     
*/
    
public   final   void  testDeleteOrgTypeInfo() {
        fail(
" 尚未实现 " );  //  TODO
    }

    
/**  
     * {
@link  OrgTypeDAO#updateOrgTypeInfo(com.zhjy.mltx.vo.OrgTypeVO)} 的测试方法。
     
*/
    
public   final   void  testUpdateOrgTypeInfo() {
        fail(
" 尚未实现 " );  //  TODO
    }

    
/**  
     * {
@link  OrgTypeDAO#getOrgTypeInfoById(java.lang.String)} 的测试方法。
     
*/
    
public   final   void  testGetOrgTypeInfoById() {
        fail(
" 尚未实现 " );  //  TODO
    }

    
/**  
     * {
@link  OrgTypeDAO#isRepeatOrgTypeInfo(java.lang.String)} 的测试方法。
     
*/
    
public   final   void  testIsRepeatOrgTypeInfoString(){
        fail(
" 尚未实现 " );  //  TODO
    }

    
/**  
     * {
@link  OrgTypeDAO#isRepeatOrgTypeInfo(com.zhjy.mltx.vo.OrgTypeVO)} 的测试方法。
     
*/
    
public   final   void  testIsRepeatOrgTypeInfoOrgTypeVO() {
        fail(
" 尚未实现 " );  //  TODO
    }

    
/**  
     * {
@link  OrgTypeDAO#getFlatOrgIdByName(java.lang.String)} 的测试方法。
     
*/
    
public   final   void  testGetFlatOrgIdByName() {
        fail(
" 尚未实现 " );  //  TODO
    }
}


JUnit单元测试一共要注意一下几点:
1 import junit.framework.TestCase junit.textui.TestRunner
2 )继承 junit.framework.TestCase
3 )自行添加一个 main 方法      中调用 TestRunner.run( 测试类名 .class);
4 )有一个调用 super(String) 的构造函数;
        以上都是 JUnit 必有的特征,除以上外,我们发现有许多以 test 开头的方法,而这些方法正是我们要测试的方法, Junti 测试其实采用的是断言的方式,只要我们在所有 test 开头中的方法对数据添加断言方法,同时提供很多断言的方法,

 

常用断言方法
assertEquals(" 失败提示信息 "," 期望数据 "," 测试数据 ")
断言获取数据是否与所期望的相等
assertNotNull(" 失败提示信息 "," 测试数据 ")
断言获取数据不为 null ,否则提示错误
assertNull(" 失败提示信息 "," 测试数据 ")
断言获取数据是为 null ,否则提示错误
assertTrue(" 失败提示信息 ", 测试数据 blooean )
断言获取数据是否为 ture ,否则提示错误
fail(" 失败提示信息 ");
此方法一般放到异常处,遇到此方法,测试将停止 !
assertSame(" 失败提示信息 "," 期望数据 "," 测试数据 ")
断言获取数据是否与所期望的相同
当我们写完所有方法策略后, JUnit 测试如下图:
在方法页面中点击右键在 调试方式 运行方式 中点击 JUnit 测试 ,就运行测试类!
在执行测试类时,执行的大概过程
1 )先执行构造方法 public OrgTypeDAOTest(String arg0)
2 )再执行初始化数据方法 protected void setUp()
3 )再执行以 test 开头的测试方法;
4 )最后执行 protected void tearDown() 方法清理对象;
如果测试失败或者错误,将会显示一个红色的亮条;如果测试通过将显示绿色亮条;如下图
 
这样就把一个整个单元测试操作例子演示完成!
可能对于一个测试类中有多个方法要测试,对于后面看着的确有些困难,因此,我对上测试类进行简单的调整,如下代码:
 import junit.framework.TestCase;
import junit.textui.TestRunner;
//import com.zhjy.mock.SpringMock;
/**
 * 举例测试类
 */
public class OrgTypeDAOTest extends TestCase {    //(1)继承TestCase
    //private OrgTypeDAO orgTypeDAO;
    //private OrgTypeVO orgTypeVO;
    //private String id ;
    /**
     *  构造方法
     * @param arg0
     */
    public OrgTypeDAOTest(String arg0) {
        super(arg0);
    }   
    /**
     *初时化方法
      * @see junit.framework.TestCase#setUp()
     */
    protected void setUp() throws Exception {
        super.setUp();
        //测试初始话数据调用类 orgTypeDAO和 封装数据的对象orgTypeVO
    }
    /** 执行完清理方法
     * @see junit.framework.TestCase#tearDown()
     */
    protected void tearDown() throws Exception {
        //清空 对象  ;==null
        //orgTypeDAO =null;
        //orgTypeVO =null;
        super.tearDown();
    }
    /**
     *  主函数
     * @param args
     */
    public static void main(String[] args){
        TestRunner.run(OrgTypeDAOTest.class);
    }
    /**
     * 测试方法
     * Test method testOrgTypeInfo
     */
    public void testOrgTypeInfo() {
        //添加
        String id = insertOrgTypeInfo();
        //列表
        orgTypeList();
        //修改
        updateOrgTypeInfo(id);
        //查询
        selectOrgTypeInfoById(id);
        //校验
        iExistOrgByOrgTypeId(id);
        //测试是否重复数据方法(add)
        isRepeatOrgTypeInfo(orgTypeVO.getName(),"");
        //获取数据方法(根据名称)
        selectOrgTypeIdByName(orgTypeVO.getName());
        //删除
        deleteOrgTypeInfo(id);
    }
    /**
     *添加初始数据
     */
    private void setOrgTypeVOAddInfo() {
        orgTypeVO.setName("add中海测试");
        orgTypeVO.setDescription("add中海测试");
        orgTypeVO.setStatus("1");
    }
    /**
     *添加初始数据
     */
    private void setOrgTypeVOUpdateInfo(){
       
        //orgTypeVO.setId(id);
        orgTypeVO.setName("add中海测试");
        orgTypeVO.setDescription("update中海测试");
        orgTypeVO.setStatus("1");
    }
    /**
     * 新增方法
     * Test method for {@link OrgTypeDAO#insertOrgTypeInfo(com.zhjy.mltx.vo.OrgTypeVO)}.
     */
    public String insertOrgTypeInfo(){
        setOrgTypeVOAddInfo();
        String id = null;
        try{
            id = orgTypeDAO.insertOrgTypeInfo(orgTypeVO);
        }catch(Exception e){
            fail("添加通用组织机构失败!");
        }
        return id;
    }
    /**
     * 更新方法
     * Test method for {@link com.zhjy.mltx.dao.OrgTypeDAO#updateOrgTypeInfo(com.zhjy.mltx.vo.OrgTypeVO)}.
     */
    public void updateOrgTypeInfo(String id) {
        setOrgTypeVOUpdateInfo();
        orgTypeVO.setId(id);
        try{
            orgTypeDAO.updateOrgTypeInfo(orgTypeVO);
        }catch(Exception e){
            assertTrue("修改通用组织机构失败!", false);
        }
        //查询
        orgTypeVO = orgTypeDAO.selectOrgTypeInfoById(id);
        assertEquals("修改通用组织机构失败!", orgTypeVO.getDescription(), "update中海测试");
    }
    /**
     * 获取数据方法(主健)
     * Test method for {@link OrgTypeDAO#selectOrgTypeInfoById(java.lang.String)}.
     */
    public void selectOrgTypeInfoById(String id) {
        orgTypeVO = orgTypeDAO.selectOrgTypeInfoById(id);
        assertTrue("无法查看一条通用机构名称信息!",orgTypeVO != null);
        assertEquals("添加通用组织机构失败!", orgTypeVO.getName(), "add中海测试");
        assertEquals("修改通用组织机构失败!", orgTypeVO.getDescription(), "update中海测试");
    }
    /**
     * 测试此通用组织机构是否被引用
     * Test method for {@link OrgTypeDAO#iExistOrgByOrgTypeId(java.lang.String)}.
     */
    public void iExistOrgByOrgTypeId(String id){
        boolean isfalse;
        try {
            isfalse = this.orgTypeDAO.iExistOrgByOrgTypeId(id);
            assertFalse("通用组织机构校验错误!",isfalse);
        } catch (DataAccessException e) {
            assertTrue("通用组织机构数据操作错误!!",false);
        } catch (ObjectNotFoundException e) {
            assertTrue("id is null!!",false);
        }
       
    }
    /**
     * 删除
     * Test method for {@link OrgTypeDAO#deleteOrgTypeInfo(java.lang.String)}.
     */
    public void deleteOrgTypeInfo(String id) {
        this.orgTypeDAO.deleteOrgTypeInfo(id);
        orgTypeVO = this.orgTypeDAO.selectOrgTypeInfoById(id);
        assertNull("删除通用组织机构失败!", orgTypeVO);
    }
    /**
     * 获取数据方法(根据名称)
     * Test method for {@link OrgTypeDAO#selectOrgTypeIdByName(java.lang.String)}.
     */
    public void selectOrgTypeIdByName(String name) {
        String orgtypeid = orgTypeDAO.selectOrgTypeIdByName(name);
        //assertEquals(orgtypeid, id);
        assertNotNull("未查出来通用组织机构ID!",orgtypeid);
    }
    /**
     * 测试是否重复数据方法
     * Test method for {@link OrgTypeDAO#isRepeatOrgTypeInfo(com.zhjy.mltx.vo.OrgTypeVO)}.
     */
    public void isRepeatOrgTypeInfo(String name,String id) {
        //setOrgTypeVOUpdateInfo();
        OrgTypeVO orgtypetest = new OrgTypeVO();
        orgtypetest.setId(id);
        orgtypetest.setName(name);
        boolean isTrue = orgTypeDAO.isRepeatOrgTypeInfo(orgtypetest);
        //assertEquals("通用组织机构错误数据",isTrue, false);
        assertTrue("通用组织机构错误数据", isTrue);
    }
    /**
     * 列表方法
     * Test method for {@link com.zhjy.mltx.dao.OrgTypeDAO#orgTypeList()}.
     */
    public void orgTypeList() {
        List list = orgTypeDAO.orgTypeList();
        assertNotNull("无法获取通用机构名称列表list is null!",list);
    }
}
处理过程:
1 )把所有以 test 开头的方法中的方法名称前的 test 去掉(例如把 testOrgTypeList() 改为 orgTypeList() 方法);
2 )同时添加一个以 test 开头的方法,并调用测试方法;这样做主要是因为执行测试时 JUnit (除本身特有的方法出外)只执行以 test 为开头的方法;
3 )同时大家注意到我还把测试初始数据放到两个 private 方法中 private void setOrgTypeVOAddInfo() private void setOrgTypeVOUpdateInfo() 方法中供调用;
        大家可能认为很简单,就是这样简单的改动带来很大的方便,大家是否注意到,我以后运行测试用例时,只关心 public void testOrgTypeInfo() 方法就行了,因为只要各个方法的断言策略定制完成,一般就不会再改动,因此,后期的回归测试还是验收测试,缩小了我们对测试的关注点,同时对后面写 test suite 构建整体测试带来极大方便性!其中的好处相信只有使用才能体会!
     说到这,就此暂告一段落!由于时间仓促,书写不规范和关于任何问题处敬请指出,相互探讨.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值