您的位置:首页 > 运维架构 > Apache

Apache Ant+Junit对Java(非mvc模式)工程进行测试(一)

2013-12-19 10:44 483 查看
最近,项目开发过程中,要求采用Apache Ant与Junit开源项目对Java工程测试,网络上介绍测试的大多数都不能直接测试成功,特别是在采用Ant脚本进行测试的环节,差不多都是转载、复制、粘贴,估计博客当事人也没有测试过。

下面介绍关于测试的实现过程(首先声明:该测试过程中的Java实例,是引用或者修改过来的,还是很感谢网上的大牛):

一、环境配置

环境:主机----Windows下开发;Eclipse Version: 3.4.1

版本:JDK----1.6(安装版); Tomcat----6.0.18(安装版);Ant----apache-ant-1.7.1(解压版)

二、安装

1、安装JDK,目标盘符:D:\Program Files\Java\jdk1.6.0_07。

2、配置JDK环境变量:

2.1、建立系统变量:JAVA_HOME=D:\Program Files\Java\jdk1.6.0_07;

2.2、建立系统变量:CLASSPATH=.;(逗号+分号);

2.3、编辑path系统变量:在最前面加上%JAVA_HOME%\bin;。(第一个分号不能丢)

3、安装Tomcat,目标盘符:D:\Program Files\Apache Software Foundation\Tomcat 6.0,安装之后运行一次,查看是否安装正确或运行正常,端口8088。

注:1、安装Tomcat的时候,如果你的C盘有如此目录:C:\Program Files\Java\jre*,则Tomcat会优先选择此目录作为安装条件,故要留意此种情况;

2、虚拟机中的JDK和Tomcat 的安装方式类似,本人虚拟机由于安装的时候只有一个盘符C,故全部都安装在C盘中了;

3、采用上述安装方式,不再需要单独配置Tomcat的环境变量了。

4、解压apache-ant-1.7.1-bin.zip文件,将解压后的文件夹apache-ant-1.7.1放置在D:\Program Files\apache-ant-1.7.1下。

5、配置Ant环境变量:

5.1、建立系统变量:ANT_HOME=D:\Program Files\apache-ant-1.7.1;

5.2、编辑path系统变量:在最前面加上%ANT_HOME%\bin;;(第一个分号不能丢)

5.3、测试Ant安装是否成功,在window的命令窗口执行 ant 命令,出现:

Buildfile: build.xml does not exist!

Build failed

出现如上信息,表示Ant安装成功。

三、建立Java工程及包、功能类、功能测试类、Ant配置文件

1、建立Java项目工程:

1.1、建立java工程;

1.2、将junit.jar包放置在web-inf/lib目录下;

1.3、点击Eclipse-->Preferences,进入窗口,选择Ant选项,配置相关信息,如图(1):



图(1) 装入Junit.jar

1.4、配置Global Entries目录下的junit.jar包;

1.5、检查Ant Home Entries目录下的jar包是否在1.7.0版本及其以上,如图(2):



图(2) 装入Ant框架

1.6、整个工程目录图,如图(3):



图(3) Java工程目录结构

1.7、配置Junit整个工程目录图,如图(4):



图(4) 装入Junit框架

2、在com.pro.test包下建立功能类:

建立Calculator类,对数字进行计算:分别描述加、减、乘、除等功能

package com.pro.test;

/**
* @author limingzhong
* @desc the calculator of math
*/
public class Calculator {

private static int result;  // 静态变量,用于存储运行结果

// 加
public void add(int n) {
result = result + n;
}

// 减 bug
public void substract(int n) {
result = result - 1;
}

//乘
public void multiply(int n) {
result = result * n;
}

//除
public void divide(int n) {
result = result / n;
}

//平方
public void square(int n) {
result = n * n;
}

//Bug : 死循环
public void squareRoot(int n)  {
for (; ;) ;
}

// 将结果清零
public void clear() {
result = 0;
}

public int getResult() {
return result;
}
}

建立WordHandleUtil类,对字符串做规则处理:按照Java编程风格进行处理功能

package com.pro.test;

import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author limingzhong
* @desc the Handle of Word
*/
public class WordHandleUtil {
public static String formatHandle(String name){
if(name == null){
return null;
}
Pattern p = Pattern.compile("[A-Z]");
Matcher m = p.matcher(name);
StringBuffer sb = new StringBuffer();

while(m.find()){
if(m.start() != 0){
m.appendReplacement(sb, ("_"+m.group()).toLowerCase());
}
}
return m.appendTail(sb).toString().toLowerCase();
}
}

3、建立功能测试类:

建立CalculatorTest类,对数字进行计算的功能测试类:

package com.test.corejunit;

import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import com.pro.test.Calculator;

/**
* @author limingzhong
* @desc the test class of calculator
*/
public class CalculatorTest {

private static Calculator calculator = new Calculator();

@Before
public void setUp() throws Exception {
calculator.clear();
}
@After
public void destroy(){
}

@Test
public void testAdd() {
calculator.add(2);
calculator.add(3);
assertEquals(5, calculator.getResult());
}

@Test
public void testSubstract() {
calculator.add(10);
calculator.substract(2);
assertEquals(8, calculator.getResult());
}

@Ignore("Multiply() Not yet implemented")
@Test
public void testMultiply() {
fail("Not yet implemented");
}

@Test
public void testDivide() {
calculator.add(8);
calculator.divide(2);
assertEquals(4, calculator.getResult());
}
}

建立TestWordHandleUtil类,对字符串做规则处理的功能类:

package com.test.corejunit;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import com.pro.test.WordHandleUtil;

/**
* @author limingzhong
* @desc the test class of word handles
*/
public class TestWordHandleUtil {

@Before
public void init(){
System.out.println("方法级别初始化");
}

@BeforeClass
public static void dbInit(){
System.out.println("类级别初始化");
}

@AfterClass
public static void dbClose(){
System.out.println("类级别销毁");
}

@After
public void destroy(){
System.out.println("方法级别销毁");
}

@Test
public void formatNormal(){
String target = "employeeInfo";
String result = WordHandleUtil.formatHandle(target);
assertEquals("employee_info", result);
}

// 测试 null 时的处理情况
@Test
public void formatNull(){
String target = null;
String result = WordHandleUtil.formatHandle(target);
assertNull(result);
}

// 测试空字符串的处理情况
@Test
public void formatEmpty(){
String target = "";
String result = WordHandleUtil.formatHandle(target);
assertEquals("", result);
}

// 测试当首字母大写时的情况
@Ignore("db is down")
@Test
public void formatIgnore(){
System.out.println("忽略Test");
String target = "EmployeeInfo";
String result = WordHandleUtil.formatHandle(target);
assertEquals("employee_info", result);
}

// 测试当尾字母为大写时的情况
@Test
public void formatEnd(){
String target = "employeeInfoA";
String result = WordHandleUtil.formatHandle(target);
assertEquals("employee_info_a", result);
}

// 测试多个相连字母大写时的情况
@Test
public void formatTogether(){
String target = "employeeAInfo";
String result = WordHandleUtil.formatHandle(target);
assertEquals("employee_a_info", result);
}
}

建立TestWordHandleUtilWithParam类,参数化配置功能测试类:

package com.test.corejunit;

import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import com.pro.test.WordHandleUtil;

/**
* @author limingzhong
* @desc the method of test with param
*/
@RunWith(Parameterized.class)
public class TestWordHandleUtilWithParam {

private String expected;

private String target;

@SuppressWarnings("unchecked")
@Parameters
public static Collection words(){
return Arrays.asList(new Object[][]{
{"employee_info", "employeeInfo"},      // 测试一般的处理情况
{null, null},                           // 测试 null 时的处理情况
{"", ""},                               // 测试空字符串时的处理情况
{"employee_info", "EmployeeInfo"},      // 测试当首字母大写时的情况
{"employee_info_a", "employeeInfoA"},   // 测试当尾字母为大写时的情况
{"employee_a_info", "employeeAInfo"}    // 测试多个相连字母大写时的情况
});
}

/**
* 参数化测试必须的构造函数
* @param expected     期望的测试结果,对应参数集中的第一个参数
* @param target     测试数据,对应参数集中的第二个参数
*/
public TestWordHandleUtilWithParam(String expected , String target){
this.expected = expected;
this.target = target;
}

/**
* 测试将 Java 对象名称到数据库名称的转换
*/
@Test public void test(){
assertEquals(expected, WordHandleUtil.formatHandle(target));
}
}

建立RunAllUtilTestsSuite类,打包功能测试类:

package com.test.corejunit;

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
/**
* @author limingzhong
* @desc the method of test with making package
*/
@RunWith(Suite.class)
@Suite.SuiteClasses({
CalculatorTest.class,
TestWordHandleUtil.class,
TestWordHandleUtilWithParam.class
})
public class RunAllUtilTestsSuite {}

4、Ant配置文件build.xml:

<?xml version="1.0"?>
<project name="The union test of Java Project with Ant And Junit" default="main" basedir=".">
<property name="src" value="src"/>
<property name="testsrc" value="testsrc"/>
<property name="build" value="build/classes"/>
<property name="lib" value="WebContent/WEB-INF/lib" />
<property name="dist" value="dist"/>
<property name="classpath" location="${build}"/>

<!--配置运行时classpath -->
<path id="classpath.run">
<pathelement path="${classpath}"/>
<fileset dir="${lib}">
<include name="*.jar"/>
</fileset>
</path>

<!--配置测试时classpath-->
<path id="classpath.test">
<path refid="classpath.run"/>
<path location="${dist}/lib/test-${DSTAMP}.jar"/>
</path>

<!--任务初始化-->
<target name="init" >
<tstamp/>
<delete dir="${report}"/>
<delete dir="${dist}"/>
</target>

<!--配置编译任务 -->
<target name="compile" depends="init">
<javac srcdir="${src}" destdir="${build}">
<classpath refid="classpath.run" />
</javac>
<javac srcdir="${testsrc}" destdir="${build}">
<classpath refid="classpath.run" />
</javac>
</target>

<!--配置打包任务 -->
<target name="dist" depends="compile">
<mkdir dir="${dist}/lib"/>
<jar jarfile="${dist}/lib/test-${DSTAMP}.jar" basedir="${build}"/>
</target>

<target name="run" depends="compile, dist">
<java classname="${testsrc}/com.test.corejunit.RunAllUtilTestsSuite">
<classpath>
<path refid="classpath.run"/>
</classpath>
</java>
</target>

<!--配置测试报告的属性 -->
<property name="report"   value="report"/>
<property name="report.xml" value="${report}/junit/xml"/>
<property name="report.html" value="${report}/junit/html"/>
<target name="unittest" depends="compile,dist">
<mkdir dir="${report.xml}"/>
<mkdir dir="${report.html}"/>
<junit printsummary="yes" haltonfailure="no">
<classpath refid="classpath.run"/>
<formatter type="xml"/>
<batchtest fork="yes" todir="${report.xml}">
<fileset dir="${testsrc}" includes="**/*.java"/>
</batchtest>
</junit>
<junitreport todir="${report.html}">
<fileset dir="${report.xml}">
<include name="*.xml"/>
</fileset>
<report format="frames" todir="${report.html}"/>
</junitreport>
</target>

<!--将报表文件复制到WebContent下-->
<property name="WebContent/report" value="WebContent/${report}"/>
<target name="main" depends="unittest">
<mkdir dir="WebContent/${report}"/>
<copy todir="${WebContent/report}">
<fileset dir="${report}"/>
</copy>
</target>
</project>

至此应该建立的文件已经建立完毕。

注:在功能测试类中,采用Java注解的方式进行标注测试,一般采用的注解关键字有@Test、@Ignore、@Before、@After、@BeforeClass、@AfterClass等。关键字的具体含义及其用途、以及参数化测试、打包测试等概念请查阅相应的文档,故不在此介绍。

至此已经可以对我们要测试的功能类中的方法进行测试了,具体操作,如图(5):



图(5) 在Eclipse中执行测试类过程

结果如图(6)所示:



图(6) 在Eclipse中执行测试类结果

从图中我们可以看到,有一个方法测试的方法存在BUG,有两个方法被忽略测试。所有这次测试报红。

从图中我们还可以看到,我们测试的是一个打包功能的测试类RunAllUtilTestsSuite.java,在该类的打包注解中包括了CalculatorTest.java、TestWordHandleUtil.java、TestWordHandleUtilWithParam.java三个测试类,并且可以看到每一个测试类都测试哪些方法,每一个方法是否都测试通过等相关情况。

四、Ant配置文件(build.xml)

关于Ant配置文件,请查阅相关的官方文档,了解相关标签的含义、用途、作用域、属性等。

推荐一篇关于Ant配置文件详解的博客文章:
http://www.cnblogs.com/clarkchen/archive/2011/03/10/1980194.html
五、运行Ant

1、在Eclipse中直接运行Ant配置文件,方法如图(7):



图(7) 执行在Eclipse中运行Build Ant过程

运行结果如图(8):



图(8) 执行在Eclipse中运行Build Ant结果

从图(8)中我们可以看到两个问题:

(1)、有两个功能测试类呈现红色,而且明确提示“FAILED“,表明程序出现了BUG;

(2)、在junitreport标签中,我们的配置文件出现“Error!”提示。

上面两个问题,导致我们的结果:BUILD FAILED。

第一个问题当然是我们的程序BUG造成的,这个问题显而易见,但是第二个问题是不是呢?

第二个试了很久,原来是jre里的比jdk里的jre的少一个server端的java虚拟机:

所以我们在建立工程时需要注意两点:

(1)、junit包外部导入;

(2)、配置环境中配置jre(这个环境设置的话用开发jre:jdk/jre,不要用共同jre)。

2、当然我们一般执行Ant命令的时候,因为不是每个环境下都有Eclipse等开发工具,所以一般都在命令窗口下运行Ant,而且Ant是跨平台的,在cmd命令窗口下执行结果,如图(9)所示:





图(9) cmd命令窗口下执行Ant命令过程及其结果

从图(9)中我们可以看到,我们执行Ant命令已经成功,那么我们再来看我们的工程目录结构都发生了什么变化?

新的工程目录结构如图(10):





图(10) 执行Ant命令后的新工程目录

从图(10)中我们可以看到,新增了三个目录,即:dist、report、WebContent/report。

那么这些目录时如何生成的呢,我们来看build.xml文件:

<!--配置打包任务 -->
<target name="dist" depends="compile">
<mkdir dir="${dist}/lib"/>
<jar jarfile="${dist}/lib/test-${DSTAMP}.jar" basedir="${build}"/>
</target>

从代码中可以看到,<mkdir>标签负责生成${dist}/lib目录,知道linux等系统都知道<mkdir>命令,${dist}是一个变量,指向<project>中的dist属性,即:

<property name="dist" value="dist"/>

从${DSTAMP}变量是指在执行的时候获取系统的时间戳。

report目录类似。

WebContent/report目录生成的代码如下:

<target name="main" depends="unittest">
<mkdir dir="WebContent/${report}"/>
<copy todir="${WebContent/report}">
<fileset dir="${report}"/>
</copy>
</target>

从以上代码中,我们可以看到,这么目录下的内容都是采用拷贝的方式拷贝过去的,其中todir表示目标目录,要拷贝的内容包括${report}目录下的所有文件。

至此,Ant执行结束。

六、Ant执行结果报告

启动工程,在浏览器中输入http://localhost:8088/test/report/junit/html/index.html地址即可查看报告,如图(11)。



图(11) 测试结果报告

从图(11)中我们可以看到,本次执行Ant命令时,执行了哪些功能测试类,在点开相关的功能测试类,我们可以得到更加详细的测试数据情况,比如测试的环境参数,如图(12)、测试类中的变量输出值、测试结果,如图(13)等。



图(12) 测试参数报告



图(13) 测试结果报告

七、资源下载地址(联合测试DEMO)
http://download.csdn.net/detail/limingzhong198/6740543
至此整个过程结束,打完收工
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: