`
mizhao1984
  • 浏览: 88352 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论
阅读更多

一.前言

迄今为止,测试是我们所能找到的能确保交付的软件正常运行的最好方法。测试同编码活动越接近,从代码获得的反馈就越快。

为什么要单元测试?

1.      单元测试可以降低不确定性从而降低风险

    这里所说的软件的不确定性的原因是由于bug的存在,一旦bug出现了,那么你在修复这个bug之前基本上无法知道这个bug是多久前产生的,定位bug可能耗去半个小时还是几天,这取决于你的经验,心理状态,还有运气

从表面上看,为每个单元都编写测试代码增加了工作量,但可以帮你迅速定位错误从而大幅度减少对调试器的依赖,还有助于优化设计,并可以当文档用。

我们可以把不确定的时间转化成编写并运行的单元测试使之通过的相对可确定的时间,而编写单元测试并不是什么难事,也不会给你带来大悲大喜的情绪起伏,非常有利于我们的心脏健康

2.      单元测试可以帮助优化设计

既然自己写的代码自己要测,那么我们当然不会自找麻烦地写出难以测试的代码出来。巧的是,容易测试的代码基本上是可以和设计良好的代码划等号,因为一个测试用例其实也就是一个单元最早的用户,容易使用显然意味着良好的设计

3.      单元测试用例可以当文档说明

通过测试用例我们就可以知道被测试的代码所起的作用。

 

二.JUnit基础知识

2.1  概念

JUnit是一个开发源代码的Java测试框架,用于编写和运行可重复的测试。主要用于白盒测试,回归测试。

JUnit是以jar文件(junit.jar)的形式分发的。为了使用JUint来为你的应用程序编写测试,你只需把JUnitjar文件添加到你的项目中。

    一些运行JUnit相关的开源帮助工具:

Cactus,用于对J2EE组件进行单元测试(http://jakarta.apache.org/cactus/

Mock Objects,用于对任何代码进行单元测试(http://www.mockobjects.com/

Maven,用于构建和持续构建(http://maven.apache.org/

Ant,编译和测试程序的构建工具(http://ant.apache.org

Clover,测试覆盖工具

 

2.2  JUnit中常用的接口和类

1.Test接口:运行测试和收集测试结果;Test接口使用了Composite设计模式,是单独测试用例(TestCase),聚合测试模式(TestSuite)及测试扩展(TestDecorator)的共同接口。

主要方法:

countTestCases:统计TestCases 数目
run:运行测试并将结果返回到指定的TestResult 中

2. TestCase是Test接口的抽象实现,(不能被实例化,只能被继承)其构造函数TestCase(string name)根据输入的测试名称name创建一个测试实例。

主要方法:
countTestCases:返回TestCase 数目,直接返回1
getName,返回TestCase 当前准备允许的测试方法的名称(私有属性fName)

run:运行TestCase,如果没有指定结果存储的TestResult,将调用createResu(lt
方法。
注意,TestCase TestResult 会有互相调用。

3. Assert静态类——一系列断言方法的集合,包含了一组静态的测试方法,用于期望值和实际值比对是否正确,即测试失败

主要方法:

assert:保留(deprecated)方法,判断一个条件是否为真
assertTrue:assert 的替代方法,判断一个条件是否为真
assertEquals:用于判断实际值和期望值是否相同(Equals),可以是各种JAVA
对象。

assertNotNull:判断一个对象是否不为空
assertNull:判断一个对象是否为空
assertSame:判断实际值和期望值是否为同一个对象( ==),注意和assertEquals区分
failNotEquals:主要用于assertEquals 方法,调用fail 返回失败提示
failNotSame:主要用于assertSame 方法,调用fail 返回失败提示

 

4. TestSuite测试包类——多个测试的组合,负责组装多个Test Cases

主要方法:

addTest:增加一个TestSuit 的实例到fTests中。注意由于TestCase 的
实例化实际上只指定一个测试方法,即增加一个TestCase 的实例是注册了其中一
个测试方法,参看TestCase 类。如参数是一个TestSuite,则相当于增加了一个子
Suite.
addTestSuite:增加一个子Suite,实际效果同参数为TestSuite 的addTest。

countTestCases:返回Suite(包括子Suite)中的TestCase 实例(测试方法)数

run:运行测试,注意这里是运行fTests 中的所有测试,用了TestResult.
shouldStop 方法来判断是否终止运行。实际是调用了runTest
runTest:运行某一TestCase 或子Suite 的测试,注意使用了递归。如果参数test
是一个TestSuite,会再调用TestSuite.run
testAt:返回fTests 指定顺序的TestCase 或者TestSuite
testCount:返回fTests 大小,注意和countTestCases 的区别

tests:返回fTests 的内容
setName:设置名称
getName:增加名称
toString:
private
addTestMethod:增加一个测试方法(TestCase 实例)到fTests
exceptionToString:返回一个Throwable 中的提示信息

getConstructor:返回指定类的构造函数
isPublicTestMethod:判断一个方法是否是public 的测试方法,即一个函数是否
是public 的,同时是一个测试方法,测试方法参考下面的isTestMethod。
isTestMethod:判断一个方法是否是测试方法,既以test”为前缀、没有参数及
返回值。
warning:增加一个错误提示Testcase到fTests中,注意这里也使用了Anonymous
Class。warning 使用主要考虑的往往在对TestSuite 进行操作的时候,不会因为有

错就终止操作,而是在run 的时候报告错误

5. TestResult结果类集合了任意测试累加结果

主要方法:
addError:增加错误,注意这里错误应该指测试程序本身的错误或者被测试程
序错误,而不是测试失败
addFailure:增加一个测试失败,专用于AssertionFailedError 的处理
endTest:结束测试
startTest:开始测试

6. TestListener接口是个事件监听规约,可供TestRunner类使用。它通知listener的对象相关事件

7. TestFailure失败类是个失败状况的收集类,解释每次测试执行过程中出现的异常情况。其toString()方法返回失败状况的简要描述

2.3  命名和用法

     1.测试用例:

命名:

待测试类的名称+Test

:待测试类:HelloWorld.java

测试类:HelloWorldTest.java

 

  用法:

  A.继承自TestCase

  B.testXXX方法的形式包含一个或多个测试(XXX:待测试类中方法的名称)

     2.测试集合:

命名:

待测试类的名称+Test

:测试类:PayByBankTest.javaPayByCardTest.java

组合测试类:TestAllPay.java

      

       用法:

   public static Test suite(){

TestSuite suite = new TestSuite();

suite.addTestSuite(PayByBankTest.class);

suite.addTestSuite(PayByCardsTest.class);

               return suite;

}

2.4  juit控制台

 

Runs:一共运行的TestCase数量

Error:由于编译错误或程序错误所导致的测试失败

Failuresjunit发出的错误(比如:断言失败,等等)

Failure Trace:异常信息

2.5  例子

    待测试的类:

helloWorld.java(日志打印):

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

public class HelloWorld {

private static final Log log = LogFactory.getLog(HelloWorld.class);

public void print(){

   log.info("Hello world!");

}

}

CommonMethod.java(日期格式化)

import java.text.SimpleDateFormat;

import java.util.Date;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

public class CommonMethod{

    private static final Log log = LogFactory.getLog(CommonMethod.class);

    public CommonMethod(){}

    public static String fromDate(Date dObj, String format){

         if (dObj == null) return "";

         SimpleDateFormat f1;

         if (format.equals(""))format = "yyyy-MM-dd HH:mm";

         f1 = new SimpleDateFormat(format);

         try{

             return f1.format(dObj);

         }catch(Exception e){

             log.warn(e.getMessage(), e);

         }

         return null;

     }

}

XmlParse.javaxml解析):

import java.io.ByteArrayOutputStream;

import java.io.DataOutputStream;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.StringReader;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import org.dom4j.Document;

import org.dom4j.io.OutputFormat;

import org.dom4j.io.SAXReader;

import org.dom4j.io.XMLWriter;

public class XmlParse{

    private static final Log log = LogFactory.getLog(XmlParse.class);

    private XmlParse(){}

    public static Document loadXML(String xmlStr){

         Document result = null;

         try{

             SAXReader sax = new SAXReader();

             result = sax.read(new StringReader(xmlStr));

         }catch (Exception ex){

             log.info("Input XML String Err:" + ex.toString(), ex);

             throw new RuntimeException(ex);

         }

         return result;

    }

 

    public static Document loadXML(String xmlStr, String encoding){

         Document result = null;

         try{

             SAXReader sax = new SAXReader();

             sax.setEncoding(encoding);

             result = sax.read(new StringReader(xmlStr));

         }catch (Exception ex){

             log.info("Input XML String Err:" + ex.toString(), ex);

             throw new RuntimeException(ex);

         }

         return result;

   }

}

1.   TestCase用法:

CommonMethodTest

import java.util.Date;

import junit.framework.Test;

import junit.framework.TestCase;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

public class CommonMethodTest {

private static final Log log = LogFactory.getLog(CommonMethodTest.class);

public static Test suite(){

      //TestSuite suite = new TestSuite();

      TestCase testCase = new TestCase("common"){

           @Override

           protected void runTest() throws Throwable {

               String dateStr = CommonMethod.fromDate(new Date(),"yyyy-MM-dd");

               log.info(dateStr);

           }

      };

      log.info(testCase.getName());

      //String dateStr = CommonMethod.fromDate(new Date(),"yyyy-MM-dd");

      //log.info(dateStr);

      //return suite;

      return testCase;

}

}

HelloWorldTest.java

import java.util.Date;

import junit.framework.Test;

import junit.framework.TestCase;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

public class HelloWorldTest extends TestCase {

public void testPrint(){ 

   HelloWorld helloWorld = new HelloWorld();

   helloWorld.print();

}

}

XmlParseTest.java

import junit.framework.TestCase;

import org.dom4j.Document;

public class XmlParseTest extends TestCase {

private String xml;

@Override

/*

* 测试用例运行时需要加载的

* 构造xml,测试时要使用的测试数据

*/  

protected void setUp() throws Exception {

      StringBuffer stringBuffer = new StringBuffer();

      stringBuffer.append("<xml>");

      stringBuffer.append("<user>");

      stringBuffer.append("<userId>1</userId>");

      stringBuffer.append("<name>mz</name>");

      stringBuffer.append("</user>");

      stringBuffer.append("<user>");

      stringBuffer.append("<userId>2</userId>");

      stringBuffer.append("<name>sg</name>");

      stringBuffer.append("</user>");

      stringBuffer.append("</xml>");

      xml = stringBuffer.toString();

}

 

public void testLoadXMLString() {

      Document document = XmlParse.loadXML(xml);

      assertNotNull(document);

}

public void testLoadXMLStringString() {

      Document document = XmlParse.loadXML(xml,"GB2312");

      assertNotNull(document);

     

}

}

2. TestSuite用法:
TestAll.java:
import junit.framework.Test;
import junit.framework.TestSuite;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class TestAll{
 private static final Log log = LogFactory.getLog(TestAll.class);
 public static Test suite(){
  //TestSuite 用于组合测试
  TestSuite suite = new TestSuite();
  suite.addTestSuite(XmlParseTest.class);
  suite.addTestSuite(HelloWorldTest.class);
  suite.addTest(CommonMethodTest.suite());
  log.info("组合测试");
  log.info("countTestCases:" + suite.countTestCases());;
  
  return suite;
 }
}

分享到:
评论

相关推荐

    Junit基础教程与学习

    此文档非常有助于刚刚接触junit的人来学习,图文并茂,很容易上手!

    Android Studio JUnit基础

    Android Studio单元测试快速入门

    JUnit4基础文档

    JUnit4基础文档

    Junit基础培训

    Junit是unit中的一类,比较好比较实用,大家可以学习一下

    junit5.rar包含JUnit Platform + JUnit Jupiter + JUnit Vintage依赖jar包

    JUnit Platform是在JVM上启动测试框架的基础。 JUnit Jupiter是JUnit5扩展的新的编程模型和扩展模型,用来编写测试用例。Jupiter子项目为在平台上运行Jupiter的测试提供了一个TestEngine (测试引擎)。 JUnit ...

    软体测试架构junit

    软体测试架构junit(葉秉哲) JUnit 的定位 JUnit 基础篇 JUnit 进阶篇

    Junit 5中文帮助指南

    JUnit Platform是在JVM上 启动测试框架 的基础平台。它还定义了 TestEngine API,该API可用于开发在平台上运行的测试框架。此外,平台还提供了一个从命令行或者 Gradle 和 Maven 插件来启动的 控制台启动器 ,它就...

    junit4基础教程

    junit4基础教程合集,适合初学者学习,简单明了,易于学习,希望大家能认真阅读

    Junit实战第二版

    可以复制,并且有目录。... 《JUnit实战(第2版)》适合于已具有一定Ja va编程基础的读者,以及在Java平台下进行各类软件开发的开发人员、测试人员。对于单元测试学习者和编程爱好者来说,本书则具有极高的学习参考价值。

    JUnit是什么?介绍

    JUnit 软件基础介绍

    JUnit_完整教程_基础_实例

    JUnit_完整教程_基础_实例 JUnit_完整教程_基础_实例

    Junit实战第二版 中文完整版

    JUnit实战(第2版)本书从认识JUnit、不同的测试策略、JUnit与构建过程、JUnit扩展4个方面,由浅入深、由易到难地对JUnit展开了系统的讲解,包括探索JUnit的核心、软件测试原则、测试覆盖率与开发、使用stub进行粗粒度...

    JUnit 5.pdf

    JUnit 5中文学习文档。JUnit 5是JUnit的下一代。目标是为JVM上的开发人员端测试创建一个最新的基础。这包括专注于Java 8及更高版 本,以及启用许多不同风格的测试。

    JUnit实战 第2版 (英文版)

    《JUnit实战(第2版)》还介绍了基础的软件开发原则,如测试驱动开发(TDD)等,以便指导用户如何使用不同的工具来测试典型Java EE应用程序的每一层。此外,《JUnit实战(第2版)》也提供了几个附录,以帮助读者快速转换...

    Junit实战(第2版)

    本书从认识JUnit、不同的测试策略、JUnit与构建过程、JUnit扩展4个方面,由浅入深、由易到难地对JUnit展开了系统的讲解,包括探索JUnit的核心、软件测试原则、测试覆盖率与开发、使用stub进行粗粒度测试、使用mock...

    jUnit入门教程 jUnit教程

    学习时候从网络上整理的juint资料,非常基础.

    Junit单元测试(很经典)

    Junit单元测试,分为基础篇、中级篇和高级篇。很经典、很实用的资料. 欢迎大家分享。

    软件测试 Junit教程

    理解手工编写单元测试的基本方法; 编写简单的基于JUnit的单元测试用例; 深入掌握JUnit的核心类、JUnit生命周期。

    JUnit整合基础加开发FizzBuzz实例

    一个简单的junit的小例子。非常适合初学者哦

    基于Junit扩展的测试框架iTest.zip

    将参数的输入、请求执行、结果解析、数据验证、数据准备与清理各个环节都做了封装,以数据文本文件为...3. 数据准备与清理:构造测试数据的sql,或者service接口底层主要使用的是HttpClient JUnit 标签:iTest

Global site tag (gtag.js) - Google Analytics