一.关于Junit
关于为什么junit.jar包不能放到lib/ext目录中:
先谈谈类装载器
java虚拟机和程序都调用ClassLoader类的loadClass的方法来加载。java虚拟机中可有多个类加载器,bootstrap来加载rt.jar(java核心包),ExtClassLoader加载<JAVA_HOME>/jre/lib/ext装载jar包,AppClassLoader加载classpath环境变量指定的路径中的类。ExtClassLoader是AppClassLoader的父类。
再说junit.jar为什么不能放到lib/ext目录下的原因:
现在如果把junit.jar包放到ext目录下,ExtClassLoader类装载器要把junit.jar先装载,junit然后要去调用那个被测试类,然而那个被测试类是放在classpath中,被AppClassLoader装载,因为ExtClassLoader是AppClassLoader的父类,AppClassLoader已经装载了被测试类,ExtClassLoader并不知道APP已经装载了这个类,它还要去装载被测试类,结果找不到这个类。就会抛出异常了。但是如果把被测试类也打包为jar包放到ext目录底下应该就没问题了,但这样做单元测试的时候是不是比较麻烦?
Junit作为一个单元测试工具,在保证代码的质量上,起到比较重要的作用.我们使用的为Junit3.8.1版本,用的时候需要把junit.jar添加到项目编译和运行的classpath中,在最简单的Junit方式中,我们将所有的测试放到TestCase的子类中, 每个测试必须是public,不接受任何参数,返回void,并且以一个"test"开头的方法名(最佳实践,Junit鼓励你这么做).传统情况下,setUp()方法创建一个对象的通用集合并将其初始化,这些对象在所有的测试中都将被用到.setUp()与构造方法的区别就是:setUp()在每次测试前被调用.测试完之后,再调用tearDown()方法(可选)在每次测试后执行清除工作.
使用Junit的好处:
1、对于xp编程而言,要求在编写代码之前先写测试,这样可以强制你在写代码之前好好的思考代码(方法)的功能和逻辑,否则编写的代码很不稳定,那么你需要同时维护测试代码和实际代码,这个工作量就会大大增加。因此在xp编程中,基本过程是这样的:构思-》编写测试代码-》编写代码-》测试,而且编写测试和编写代码都是增量式的,写一点测一点,在编写以后的代码中如果发现问题可以较块的追踪到问题的原因,减小回归错误的纠错难度
2、对于重构而言,其好处和xp编程中是类似的,因为重构也是要求改一点测一点,减少回归错误造成的时间消耗。
3、对于非以上两种情况,我们在开发的时候使用junit写一些适当的测试也是有必要的,因为一般我们也是需要编写测试的代码的,可能原来不是使用的junit,如果使用junit,而且针对接口(方法)编写测试代码会减少以后的维护工作,例如以后对方法内部的修改(这个就是相当于重构的工作了)。另外就是因为junit有断言功能,如果测试结果不通过会告诉我们那个测试不通过,为什么,而如果是想以前的一般做法是写一些测试代码看其输出结果,然后再由自己来判断结果使用正确,使用junit的好处就是这个结果是否正确的判断是它来完成的,我们只需要看看它告诉我们结果是否正确就可以了,在一般情况下会大大提高效率。

如何使用JUnit写测试?
最简单的范例如下:
1、创建一个TestCase的子类: 
package junitfaq;
import java .util.*;
import junit.framework.*;
public class SimpleTest extends TestCase {
public SimpleTest(String name) {
super(name);
}
2、写一个测试方法断言期望的结果:
public void testEmptyCollection() {
Collection collection = new ArrayList();
assertTrue(collection.isEmpty());
}
注意:JUnit推荐的做法是以test作为待测试的方法的开头,这样这些方法可以被自动找到并被测试。
3、写一个suite()方法,它会使用反射动态的创建一个包含所有的testXxxx方法的测试套件:
public static Test suite() {
return new TestSuite(SimpleTest.class);
}
4、写一个main()方法以文本运行器的方式方便的运行测试:
public static void main(String args[]) {
junit.textui.TestRunner.run(suite());
}
}
5、运行测试

我的例子
被测试类:
package cn.itcast;
public class FindChar{
  int search(char[] chars,char ch) {
   //throw new UnsupportedOperationException("");
   int i=0;
   int index=0;
   boolean b=false;
   
   if(chars==null){
     throw new IllegalArgumentException();
   }
   for(;i<chars.length;i++){
    if(chars[i]==ch){
   //   index=i;
      b=true;
      break;
    }
    else{
       index=-1;
        b=false; 
    }
   }
   if(b=true){
     return index; 
   }
   else
       return index;
  } 
}
测试用例:
package cn.itcast;
import junit.framework.*;
public class TestFindChar extends TestCase{
  private FindChar fc=null;
  private char[] chars={'a','b','c'};
  public void setUp(){
    fc=new FindChar();
  }
  public void testSearchFound(){
    int index=fc.search(chars,'c');
    assertEquals(index,2);
  }
  public void testSearchNotFound(){
     int index=fc.search(chars,'e');
     assertTrue(index==-1);
  }
  public void testSearchIllegalArguments(){
     char[] chs=null;
     fc.search(chs,'a');
     fail("this is failure");
  }
}
打开命令行窗口,set好classpath之后,把两个类都编译之后,开始测试,
输入:java  junit.swingui.TestRunner  TestFindChar
测试结果:
我们会看到一个err,和一个fail...通过一个...然后我们再去修改被测试类,之后的测试结果为:
看到了吗?红条变为绿条,表示测试全部通过....
NOTICE:error和fail的区别为:error是测试之外的错误,是无法预料的.而fail表示测试失败...你就需要去找被测试类中方法的错了....
二.Junit联手Ant
ant 我们已经很熟悉了.直接把buile.xml配置好,值得学习的是build中关于使用junit和junitreport这两个任务标签.
<?xml version="1.0" encoding="GB2312" ?>    <!--encoding属性解决了注释中文问题-->
<project name="junitlesson" default="report">
 <property file="lesson6.property"/>
 <target name="init">
  <mkdir dir="${classes.java.dir}"/>
  <mkdir dir="${classes.test.dir}"/>
 </target>
 
 <target name="compilejava" depends="init">
  <javac srcdir="${src.java.dir}/cn/itcast" destdir="${classes.java.dir}" />
  
 </target>
 
 <target name="compiletest" depends="init">
  <javac srcdir="${src.test.dir}/cn/itcast" destdir="${classes.test.dir}" >
  <classpath>
    <pathelement location="${classes.java.dir}" />
   </classpath>
  </javac> 
 </target>
 
 <target name="compile" depends="compilejava,compiletest" />
 
 <target name="clean">
   <delete dir="{classes.java.dir}" />
   <delete dir="{classes.test.dir}" />
 </target> 
 
 <target name="test" depends="clean,compile">
  <mkdir dir="reports" />
  <junit fork="true" printsummary="on"  >
  <classpath>
    <pathelement location="${classes.junit.dir}" />
   <pathelement location="${classes.java.dir}" />
   <pathelement location="${classes.test.dir}" />   
  </classpath>
  <!--test name="cn.itcast.TestFindChar" todir="." /-->
  
  <!--没有formatter就看不到输出信息,可以有多个formatter如果出错就退出了build(haltonfailure)-->
  <batchtest fork="yes" todir="reports">                    <!--批处理-->
    <fileset dir="${src.test.dir}">
<!--注意include和includes的区别,我在这吃了大亏,找这个错误浪费了我好多时间-->
 <!-- batchtest指定的java源文件或class文件,而不是要运行的测试类名称,junit从这些文件中找出要运行的测试类名-->    

      <include name="**/*Test*.java"/>             
      <exclude name="**/AllTests.java"/>
    </fileset>
  </batchtest>
  <formatter type="brief" usefile="false"/>  <!--如果没有设置formatter,将无法打印出详细的信息-->
  
  <formatter type="plain" /><!--默认usefile为true,将会自动创建txt文件-->
  <formatter type="xml" />
  
  </junit>
 </target>
 
 <target name="report" depends="test">
  <junitreport todir="." >
   <fileset dir="./reports">
    <include name="TEST-*.xml" />                      <!--根据指定文件夹中的.xml文件生成html格式的测试report-->
   </fileset>
   <report format="frames" todir="." />
  </junitreport>
 </target>
</project>
build中用到的.property文件:
src.java.dir=src/java
src.test.dir=src/test
classes.java.dir=classes/java
classes.test.dir=classes/test
class1=junit.swingui.TestRunner
classes.junit.dir=D:/junit3.8.1/junit.jar
看到没有,在build中配置的是junit.swingui.TestRunner,程序运行之后的测试结果应该显示在图形界面中,但是,ant运行以后,是以文字信息在命令行窗口中输出的,至于原因可能是 类加载器 的问题.
ant完成之后生成的.html格式的report,如下图:
这样就可以根据测试结果来完善我们的程序了,用起来也很方便的.
三.总结
在使用ant进行junit测试的时候,我们应该注意的是,在src目录下,创建java和test两个文件夹,java中放被测试类,test中放测试类,但是它们的包名是相同的,这就叫分离但等同. 还应该注意的是,classpath应该设置正确,还有脑子要清晰,否则会因为包名问题浪费过多的时间.
在极限编程(XP)中,TDD(Test Driven Development)是一种实践.测试驱动开发.我们应该养成这种测试先行的行为习惯,
注意事项:
   1.将测试类和被测试类放在同一个目录里(即同包之内)将会是很方便的.
   2.命名规则:一般被测试类写作XXXXTest,而其中的方法写作testXXX
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐