本文主要是介绍http://sourceforge.net/projects/easymock/ ant结合junit进行软件自动测试,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
http://sourceforge.net/projects/easymock/
持续集成实践三,灵感来自于Martin Fowler的“持续集成“一文。可以在www.martinfowler.com看到,国内有人翻译成了中文。
本文假设读者具备如下知识:
1、熟练ant进行java工程编译(参考本人“ant编译java工程”一文)
2、junit知识,看看www.junit.org
准备:
1、www.junit.org下载junit.jar
2、xml.apache.org下载xalan.jar(ant 的 juntreport需要用到,xalan最好版本大于2.0,不然你还要下载其他的java库)
把junit.jar、xalan.jar拷贝到$ANT_HOME/lib/下面,并且最好加到系统CLASSPATH(junit.jar是肯定要的,xalan.jar就不清楚了)。
对自己的程序添加junit测试程序,此处请参考www.junit.org的文档,很简单的。
然后在build.xml中添加如下指令,很多东西略过,所以强烈要求读者先完成本人“ant编译java工程”一文)
<!-- 单元测试,需要完成compile任务 -->
<target name="test" depends="compile">
<junit printsummary="yes">
<!-- 需要的classpath -->
<classpath refid="classpath"/>
<batchtest>
<!-- 单元测试文件为所有src目录下的*Test.java文件 -->
<fileset dir="${srcDir}"><include name="**/*Test.java"/></fileset>
<!-- 生成格式为xml,也可以用plain或者brief -->
<!-- 为什么生成xml,是为了下一步做report用 -->
<formatter type="xml"/>
</batchtest>
</junit>
<!-- 对xml文件生成相应的html文件在reports目录下 -->
<!-- 如果指定于web可访问的目录,就可以使整个项目组看到单元测试情况 -->
<junitreport todir="reports">
<fileset dir=".">
<include name="TEST-*.xml"/>
</fileset>
<!-- 带有框架,可以用noframes选不带框架 -->
<report format="frames" todir="reports/html"/>
</junitreport>
</target>
现在运行ant test,看看reports/下面是不是有了生成的单元测试结果的文件了?
如果有问题可以用ant -debug test看看问题出在哪里?
另外更改源程序,让程序通过测试和通不过测试看看生成的结果如何?
EasyMock使用简明手册
“单元测试出错了,但到底是谁的错。我的?他的?”,这种情况显然违反了测试的独立性原则。出现这种情况使得这个测试无法确切的指出是那个单元出现了问题,照成了排错的困难,而且也浪费了时间。同时,过分的将单元的测试代码依赖于其他单元,也照成了其他一些很现实的问题:
- 在所依赖的单元完成之前,无法顺利的编写单元测试。
- 产生环境的依赖性,如运行一个HttpServletRequest处理器的测试代码必须启动一个servlet容器。
所有这些问题,都可以使用Mock Object来解决。使用它的前提是,所依赖单元的接口必须定义清楚。而EasyMock正是为了这一目的而产生的。
使用目的
通过模拟unit test所需要的组件,已达到隔离各个unit test的目的。目前的版本1.1,它所需要的环境是jdk1.3.1以上和junit3.8.1以上。
可以从http://sourceforge.net/projects/easymock/处下载。
用法
1. EasyMock采用“记录-----回放”的工作模式,基本使用步骤:
- 创建Mock对象的控制对象Control。
- 从控制对象中获取所需要的Mock对象。
- 记录测试方法中所使用到的方法和返回值。
- 设置Control对象到“回放”模式。
- 进行测试。
- 在测试完毕后,确认Mock对象已经执行了刚才定义的所有操作。
2. 使用举例:假设需要测试的对象是RequestUtil,所需要测试的方法为getBoolean。此时我们需要模拟一个HttpServletRequest对象。
public void testGetStringHttpServletRequestString() {
public void testGetBoolean() {
//创建Mock对象的控制器
MockControl control= MockControl.createControl( HttpServletRequest.class);
//获取Mock对象
HttpServletRequest mock= (HttpServletRequest)control.getMock();
//设置getBoolean中要使用的方法和返回值
control.expectAndReturn( mock.getParameter( "test"), null);
//设置控制器为replay模式
control.replay();
//执行测试
assertNull( RequestUtil.getString( mock, "test"));
//确认
control.verify();
}
}
通过EasyMock,执行这段测试代码完全不需要启动一个servlet容器,在命令行的方式下即可完成,非常的方便。
3. 记录需要使用的Mock的行为。在使用一个Mock对象之前,需要设置我们要用到的方法,以及每个方法的返回值。对于那些没有设置的方法,一旦调用(控制器处于replay模式),EasyMock就会抛出异常。记录一个方法,通常可以分成2步:首先,如同使用正常对象调用这个方法;然后,使用控制器的setReturnValue函数设置即可。在1.1中,提供了expectAndReturn函数,使得2步可以合而为一。主要的函数大致如下:
- expectAndReturn,设置期望调用的函数,以及返回值
- expectAndThrow,设置期望调用的函数,同时期望该次调用抛出异常
- setReturnValue,设置上一次调用的返回值(如上次调用时,request.getparameter( “test”),此处设置request.getparameter( “test”)的返回值)
- setThrowable,设置上次调用抛出的异常
在EasyMock中还可以设置调用所执行的次数,具体细节请参见对应的javaDoc。
4. 使用举例:
MockControl control= MockControl.createControl( HttpServletRequest.class);
HttpServletRequest mock= (HttpServletRequest)control.getMock();
mock.getParameter( "test");
//设置第一次调用request.getParameter的返回值
control.setReturnValue( null, 1);
//设置第二次调用request.getParameter的返回值
control.setReturnValue("this is a test", 1);
control.replay();
assertEquals( RequestUtil.getString( mock, "test", "haha"), "haha");
assertEquals( RequestUtil.getString( mock, "test"), "this is a test");
control.verify();
5. 在Mock对象使用结束后,务必调用控制器的verify函数,以确认Mock对象的方法得到了调用。
6. 调用方法的次序,使用Strict。有时,测试代码依赖于被依赖组件的方法的次序。如在测试与数据库相关代码时,测试代码很有可能是这样的次序:先打开数据库链接,执行操作,关闭链接。为了更好的测试这样的代码,可以使用MockControl.createStrictControl()来创建一个严格的Mock对象控制器,在其中,他会规定Mock出来的对象的调用次序。
以上是EasyMock的主要使用,至于其他的用法,请参见具体的文档。
检查表
在此列出使用Mock对象来进行unit test需要注意的问题:
- 当自己动手实现Mock对象时,不要在Mock对象中实现业务逻辑。
<?xml version="1.0" encoding="gb2312"?>
<project name="Test Project" default="all" basedir=".">
<property name="src.code" value="src"/>
<property name="src.junit" value="junit"/>
<property name="lib.dir" value="lib"/>
<property name="lib.jar" value="TestClass.jar"/>
<!-- checkstyle configuration -->
<property name="checkstyle.config" value="checkstyle.xml"/>
<taskdef resource="checkstyletask.properties"
classpath="${lib.dir}/checkstyle-all-3.1.jar"/>
<!-- 输出文档 -->
<property name="doc.dir" value="doc"/>
<property name="doc.api" value="${doc.dir}/api"/>
<property name="javadoc.package" value="com.*"/>
<!-- 输出二进制文件 -->
<property name="dist.root" value="dist"/>
<property name="dist.proj" value="${dist.root}/proj"/>
<property name="dist.classes" value="${dist.proj}/classes"/>
<property name="dist.lib" value="${dist.proj}/lib"/>
<property name="dist.junit" value="${dist.root}/junit"/>
<!-- classpath -->
<path id="classpath">
<fileset dir="${lib.dir}">
<include name="**/*.jar"/>
</fileset>
</path>
<path id="proj.libs">
<fileset dir="${dist.lib}">
<include name="**/*.jar"/>
</fileset>
</path>
<target name="init">
<mkdir dir="${doc.dir}"/>
<mkdir dir="${dist.root}"/>
<mkdir dir="${dist.proj}"/>
<mkdir dir="${dist.lib}"/>
<tstamp/>
<echo message="${TSTAMP}"></echo>
</target>
<target name="all" depends="compilesrc, javadoc, checkstyle"/>
<!-- 编译源文件 -->
<target name="compilesrc" depends="init">
<mkdir dir="${dist.classes}"/>
<javac destdir="${dist.classes}" deprecation="on">
<src path="${src.code}"/>
<classpath refid="classpath"/>
</javac>
<jar jarfile="${dist.lib}/${lib.jar}" basedir="${dist.classes}">
<include name="**/*.class"/>
</jar>
</target>
<!-- 产生javadoc -->
<target name="javadoc" depends="init">
<mkdir dir="${doc.api}"/>
<javadoc packagenames="${javadoc.package}" sourcepath="${src.code}"
private="yes" defaultexcludes="yes" destdir="${doc.dir}/api">
<classpath refid="classpath"/>
</javadoc>
</target>
<!-- 编译Junit文件 -->
<target name="compilejunit" depends="compilesrc">
<mkdir dir="${dist.junit}"/>
<javac destdir="${dist.junit}" deprecation="on">
<src path="${src.junit}"/>
<classpath refid="classpath"/>
<classpath refid="proj.libs"/>
</javac>
</target>
<!-- 运行checkstyle检查代码规范 -->
<target name="checkstyle" depends="init">
<checkstyle config="${checkstyle.config}">
<fileset dir="${src.code}" includes="**/*.java"/>
<formatter type="plain"/>
<formatter type="xml" toFile="${dist.root}/checkstyle_errors.xml"/>
</checkstyle>
</target>
<!-- 运行junit -->
<target name="junit" depends="compilejunit">
<junit printsummary="yes" haltonfailure="yes">
<classpath>
<path refid="classpath"/>
<pathelement location="${dist.junit}"/>
</classpath>
<formatter type="plain"/>
<!-- test name="com.TestClassTest" haltonfailure="no" outfile="result"/ -->
<batchtest todir="${dist.junit}">
<fileset dir="${dist.junit}" includes="**/Test*.class" />
</batchtest>
</junit>
</target>
<!-- 清除产生的类、junit相关类、文档 -->
<target name="clean">
<delete dir="${dist.classes}"/>
<delete dir="${dist.junit}"/>
<delete dir="${doc.api}"/>
</target>
<!-- 清除所有输出结果 -->
<target name="cleanall" depends="clean">
<delete dir="${doc.dir}"/>
<delete dir="${dist.root}"/>
</target>
</project>
这篇关于http://sourceforge.net/projects/easymock/ ant结合junit进行软件自动测试的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!