You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by bo...@locus.apache.org on 2000/07/20 12:02:07 UTC

cvs commit: jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/junit JUnitResultFormatter.java JUnitTask.java JUnitTest.java JUnitTestRunner.java SummaryJUnitResultFormatter.java XMLJUnitResultFormatter.java

bodewig     00/07/20 03:02:07

  Modified:    .        build.xml
               src/main/org/apache/tools/ant/taskdefs defaults.properties
  Added:       src/main/org/apache/tools/ant/taskdefs/optional/junit
                        JUnitResultFormatter.java JUnitTask.java
                        JUnitTest.java JUnitTestRunner.java
                        SummaryJUnitResultFormatter.java
                        XMLJUnitResultFormatter.java
  Log:
  Optional JUnit task.
  Submitted by:	Thomas Haas <th...@softwired-inc.com>
  
  Revision  Changes    Path
  1.42      +17 -0     jakarta-ant/build.xml
  
  Index: build.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/build.xml,v
  retrieving revision 1.41
  retrieving revision 1.42
  diff -u -r1.41 -r1.42
  --- build.xml	2000/07/19 09:16:18	1.41
  +++ build.xml	2000/07/20 10:02:01	1.42
  @@ -80,6 +80,7 @@
         <exclude name="**/WLRun.java" unless="ejb.wls.present" />
         <exclude name="**/WLStop.java" unless="ejb.wls.present" />
         <exclude name="**/EjbJar.java" unless="ejb.build" />
  +      <exclude name="**/junit/*" unless="junit.present" />
       </javac>
    
       <copydir src="${src.dir}" dest="${build.classes}">
  @@ -266,6 +267,22 @@
     <!-- Run testcase                                                        -->
     <!-- =================================================================== -->
     <target name="runtests" depends="compiletests" if="junit.present">
  +<!--
  +    This would make the buildprocess fail if using an Ant version
  +    without the junit task
  +
  +    <junit defaultprintxml="false" defaultprintsummary="true" fork="on">
  +      <classpath>
  +        <pathelement location="${lib.dir}/${name}.jar" />
  +        <pathelement location="${build.tests}" />
  +        <pathelement path="${classpath}" />
  +        <pathelement path="${java.class.path}" />
  +      </classpath>
  +
  +      <test name="org.apache.tools.ant.AllJUnitTests" />
  +    </junit>
  +-->
  +
       <java fork="yes"
             classname="junit.textui.TestRunner"
             args="org.apache.tools.ant.AllJUnitTests"
  
  
  
  1.25      +1 -0      jakarta-ant/src/main/org/apache/tools/ant/taskdefs/defaults.properties
  
  Index: defaults.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/defaults.properties,v
  retrieving revision 1.24
  retrieving revision 1.25
  diff -u -r1.24 -r1.25
  --- defaults.properties	2000/07/19 16:00:52	1.24
  +++ defaults.properties	2000/07/20 10:02:02	1.25
  @@ -49,6 +49,7 @@
   vssget=org.apache.tools.ant.taskdefs.optional.vss.MSVSSGET
   ejbjar=org.apache.tools.ant.taskdefs.optional.ejb.EjbJar
   javacc=org.apache.tools.ant.taskdefs.optional.javacc.JavaCC
  +junit=org.apache.tools.ant.taskdefs.optional.junit.JUnitTask
   
   # deprecated ant tasks (kept for back compatibility)
   javadoc2=org.apache.tools.ant.taskdefs.Javadoc
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitResultFormatter.java
  
  Index: JUnitResultFormatter.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.taskdefs.optional.junit;
  
  import junit.framework.TestListener;
  
  /**
   * This Interface describes classes that format the results of a JUnit
   * testrun.
   * 
   * @author <a href="mailto:stefan.bodewig@megabit.net">Stefan Bodewig</a>
   */
  public interface JUnitResultFormatter extends TestListener {
      /**
       * The whole testsuite started.
       */
      public void startTestSuite(JUnitTest suite);
  
      /**
       * The whole testsuite ended.
       */
      public void endTestSuite(JUnitTest suite);
  }
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
  
  Index: JUnitTask.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.taskdefs.optional.junit;
  
  import org.apache.tools.ant.BuildException;
  import org.apache.tools.ant.Path;
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.Task;
  import org.apache.tools.ant.taskdefs.*;
  import org.apache.tools.ant.types.Commandline;
  import org.apache.tools.ant.types.CommandlineJava;
  
  import java.io.File;
  import java.io.IOException;
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  
  import java.util.Enumeration;
  import java.util.Vector;
  
  /**
   * Ant task to run JUnit tests.
   *
   * <p>JUnit is a framework to create unit test. It has been initially
   * created by Erich Gamma and Kent Beck.  JUnit can be found at <a
   * href="http://www.xprogramming.com/software.htm">http://www.xprogramming.com/software.htm</a>.
   *
   * <p> This ant task runs a single TestCase. By default it spans a new
   * Java VM to prevent interferences between different testcases,
   * unless <code>fork</code> has been disabled.
   *
   * @author Thomas Haas 
   */
  public class JUnitTask extends Task {
  
      // <XXX> private final static int HALT_NOT = 1;
      // <XXX> private final static int HALT_IMMEDIATELY = 2;
      // <XXX> private final static int HALT_AT_END = 3;
  
      private CommandlineJava commandline = new CommandlineJava();
      private Vector tests = new Vector();
  
      private JUnitTest defaults = new JUnitTest();
      private boolean defaultOutfile = true;
      private Integer timeout = null;
  
      // <XXX> private int haltOnError = HALT_AT_END;
      // <XXX> private int haltOnFailure = HALT_AT_END;
  
      /**
       * Set the path to junit classes.
       * @param junit path to junit classes.
       */
      public void setJunit(String junit) {
          commandline.createClasspath().createPathElement().setLocation(junit);
      }
  
      public void setDefaulthaltonerror(boolean value) {
          defaults.setHaltonerror(value);
      }
  
      public void setDefaulthaltonfailure(boolean value) {
          defaults.setHaltonfailure(value);
      }
  
      public void setDefaultprintsummary(boolean value) {
          defaults.setPrintsummary(value);
      }
  
      public void setDefaultprintxml(boolean value) {
          defaults.setPrintxml(value);
      }
  
      public void setDefaultOutFile(boolean value) {
          defaultOutfile = value;
      }
  
      public void setTimeout(Integer value) {
          timeout = value;
      }
  
      public void setFork(boolean value) {
          defaults.setFork(value);
      }
  
      public void setJvm(String value) {
          defaults.setName(value);
  	commandline.setVm(value);
      }
  
      public void setJvmargs(String value) {
  	commandline.createVmArgument().setLine(value);
      }
  
  
      /**
       * Set the classpath to be used by the testcase.
       * @param classpath the classpath used to run the testcase.
       */
      /*public void setClasspath(String classpath) {
          this.classpath = classpath;
      }*/
  
  
      public Path createClasspath() {
          return commandline.createClasspath();
      }
  
      public JUnitTest createTest() {
          final JUnitTest result;
          result = new JUnitTest(
              defaults.getFork(),
              defaults.getHaltonerror(),
              defaults.getHaltonfailure(),
              defaults.getPrintsummary(),
              defaults.getPrintxml(),
              null, null);
  
          tests.addElement(result);
          return result;
      }
  
  
      /**
       * Creates a new JUnitRunner and enables fork of a new Java VM.
       */
      public JUnitTask() throws Exception {
          commandline.setClassname("org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner");
      }
  
      /**
       * Runs the testcase.
       */
      public void execute() throws BuildException {
          boolean errorOccurred = false;
          boolean failureOccurred = false;
  
          final String oldclasspath = System.getProperty("java.class.path");
  
          commandline.createClasspath().createPathElement().setPath(oldclasspath);
          /*
           * This doesn't work on JDK 1.1, should use a Classloader of our own 
           * anyway --SB
           *
           * System.setProperty("java.class.path", commandline.createClasspath().toString());
           */
  
          Enumeration list = tests.elements();
          while (list.hasMoreElements()) {
              final JUnitTest test = (JUnitTest)list.nextElement();
  
              final String filename = "TEST-" + test.getName() + ".xml";
  // removed --SB
  //            if (new File(filename).exists()) {
  //                project.log("Skipping " + test.getName());
  //                continue;
  //            }
              project.log("Running " + test.getName());
  
              if (defaultOutfile && (test.getOutfile() == null ||
                  test.getOutfile().length() == 0)) {
  
  // removed --SB
  //                test.setOutfile("RUNNING-" + filename);
                  test.setOutfile(filename);
              }
  
              int exitValue = 2;
  
              if (test.getFork()) {
                  try {
  		    // Create a watchdog based on the timeout attribute
                      final Execute execute = new Execute(new PumpStreamHandler(), createWatchdog());
                      final Commandline cmdl = new Commandline();
                      cmdl.addLine(commandline.getCommandline());
                      cmdl.addLine(test.getCommandline());
                      execute.setCommandline(cmdl.getCommandline());
                      log("Execute JUnit: " + cmdl, Project.MSG_VERBOSE);
                      exitValue = execute.execute();
                  }
                  catch (IOException e) {
                      throw new BuildException("Process fork failed.", e, 
                                               location);
                  }
              } else {
                  final Object[] arg = { test };
                  final Class[] argType = { arg[0].getClass() };
                  try {
                      final Class target = Class.forName("org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner");
                      final Method main = target.getMethod("runTest", argType);
                      project.log("Load JUnit: " + test, Project.MSG_VERBOSE);
                      exitValue = ((Integer)main.invoke(null, arg)).intValue();
                  } catch (InvocationTargetException e) {
                      Throwable t = e.getTargetException();
                      String msg = "Running test failed: " + t.getMessage();
                      throw new BuildException(msg, t, location);
                  } catch (Exception e) {
                      String msg = "Running test failed: " + e.getMessage();
                      throw new BuildException(msg, e, location);
                  }
              }
  
              boolean errorOccurredHere = exitValue == 2;
              boolean failureOccurredHere = exitValue == 1;
  // removed --SB
  //            if (exitValue != 0) {
  //                rename("RUNNING-" + filename, "ERROR-" + filename);
  //            } else {
  //                rename("RUNNING-" + filename, filename);
  //            }
  	    // <XXX> later distinguish HALT_AT_END case
              if (errorOccurredHere && test.getHaltonerror()
                  || failureOccurredHere && test.getHaltonfailure()) {
                  throw new BuildException("JUNIT FAILED", location);
  	    } else if (errorOccurredHere || failureOccurredHere) {
                  log("JUNIT FAILED", Project.MSG_ERR);
              }
  
  	    // Update overall test status
              errorOccurred = errorOccurred || errorOccurredHere ;
              failureOccurred = failureOccurred || failureOccurredHere ;
          }
  
  	// <XXX> later add HALT_AT_END option
          // Then test errorOccurred and failureOccurred here.
      }
  
      protected ExecuteWatchdog createWatchdog() throws BuildException {
          if (timeout == null) return null;
          return new ExecuteWatchdog(timeout.intValue());
      }
  
      private void rename(String source, String destination) throws BuildException {
          final File src = new File(source);
          final File dest = new File(destination);
  
          if (dest.exists()) dest.delete();
          src.renameTo(dest);
      }
  }
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java
  
  Index: JUnitTest.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.taskdefs.optional.junit;
  
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.types.Commandline;
  
  /**
   *
   * @author Thomas Haas
   */
  public class JUnitTest {
      private boolean systemExit = false;
      private boolean haltOnError = false;
      private boolean haltOnFail = false;
      private boolean printSummary = true;
      private boolean printXml = true;
      private String name = null;
      private String outfile = null;
      private boolean fork = false;
  
      private long runs, failures, errors;
      private long runTime;
  
      public JUnitTest() {
      }
  
      public JUnitTest(boolean fork, boolean haltOnError, boolean haltOnFail, 
                       boolean printSummary, boolean printXml, String name, 
                       String outfile) {
          this.fork = fork;
          this.haltOnError = haltOnError;
          this.haltOnFail = haltOnFail;
          this.printSummary = printSummary;
          this.printXml = printXml;
          this.name  = name;
          this.outfile = outfile;
      }
  
      public void setFork(boolean value) {
          fork = value;
      }
  
      public boolean getFork() {
          return fork;
      }
  
      public void setHaltonerror(boolean value) {
          haltOnError = value;
      }
  
      public void setHaltonfailure(boolean value) {
          haltOnFail = value;
      }
  
      public void setPrintsummary(boolean value) {
          printSummary = value;
      }
  
      public void setPrintxml(boolean value) {
          printXml = value;
      }
  
      public void setName(String value) {
          name = value;
      }
  
      public void setOutfile(String value) {
          outfile = value;
      }
  
  
      public boolean getHaltonerror() {
          return haltOnError;
      }
  
      public boolean getHaltonfailure() {
          return haltOnFail;
      }
  
      public boolean getPrintsummary() {
          return printSummary;
      }
  
      public boolean getPrintxml() {
          return printXml;
      }
  
      public String getName() {
          return name;
      }
  
      public String getOutfile() {
          return outfile;
      }
  
      public void setCommandline(String [] args) {
          for (int i=0; i<args.length; i++) {
              if (args[i] == null) continue;
              if (args[i].startsWith("haltOnError=")) {
                  haltOnError = Project.toBoolean(args[i].substring(12));
              } else if (args[i].startsWith("haltOnFailure=")) {
                  haltOnFail = Project.toBoolean(args[i].substring(14));
              } else if (args[i].startsWith("printSummary=")) {
                  printSummary = Project.toBoolean(args[i].substring(13));
              } else if (args[i].startsWith("printXML=")) {
                  printXml = Project.toBoolean(args[i].substring(9));
              } else if (args[i].startsWith("outfile=")) {
                  outfile = args[i].substring(8);
              }
          }
      }
  
      public String[] getCommandline() {
          final Commandline result = new Commandline();
          if (name != null && name.length() > 0) {
              result.setExecutable(name);
          }
          result.createArgument().setValue("exit=" + systemExit);
          result.createArgument().setValue("haltOnError=" + haltOnError);
          result.createArgument().setValue("haltOnFailure=" + haltOnFail);
          result.createArgument().setValue("printSummary=" + printSummary);
          result.createArgument().setValue("printXML=" + printXml);
          if (outfile != null && outfile.length() > 0) {
              result.createArgument().setValue("outfile=" + outfile);
          }
          return result.getCommandline();
      }
  
      public void setCounts(long runs, long failures, long errors) {
          this.runs = runs;
          this.failures = failures;
          this.errors = errors;
      }
  
      public void setRunTime(long runTime) {
          this.runTime = runTime;
      }
  
      public long runCount() {return runs;}
      public long failureCount() {return failures;}
      public long errorCount() {return errors;}
      public long getRunTime() {return runTime;}
  
  
      public String toString() {
          return Commandline.toString(getCommandline());
      }
  
  }
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java
  
  Index: JUnitTestRunner.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.taskdefs.optional.junit;
  
  import org.apache.tools.ant.Project;
  
  import junit.framework.*;
  import java.lang.reflect.*;
  import java.io.*;
  import java.util.Vector;
  
  /**
   * Simple Testrunner for JUnit that runs all tests of a testsuite.
   *
   * <p>This TestRunner expects a name of a TestCase class as its
   * argument. If this class provides a static suite() method it will be
   * called and the resulting Test will be run.
   *
   * <p>Otherwise all public methods starting with "test" and taking no
   * argument will be run.
   *
   * <p>Summary output is generated at the end.
   *
   * @author <a href="mailto:stefan.bodewig@megabit.net">Stefan Bodewig</a>
   */
  
  public class JUnitTestRunner implements TestListener {
  
      /**
       * Holds the registered formatters.
       */
      private Vector formatters = new Vector();
  
      /**
       * Collects TestResults.
       */
      private TestResult res;
  
      /**
       * Flag for endTest.
       */
      private boolean failed = true;
  
      /**
       * The test I'm going to run.
       */
      private JUnitTest junitTest;
  
      /**
       * The corresponding testsuite.
       */
      private Test suite = null;
  
      /**
       * Returncode
       */
      private int retCode = 0;
  
      public JUnitTestRunner(JUnitTest test) {
          junitTest = test;
          try {
              if (junitTest.getPrintxml()) {
                  if (test.getOutfile() != null
                      && test.getOutfile().length() > 0) {
  
                      addFormatter(new XMLJUnitResultFormatter(
                                       new PrintWriter(
                                           new FileWriter(test.getOutfile(), false)
                                               )
                                           )
                          );
                  } else {
                      addFormatter(new XMLJUnitResultFormatter(
                                       new PrintWriter(
                                           new OutputStreamWriter(System.out), true)
                                           )
                          );
                  }
              }
  
              if (junitTest.getPrintsummary()) {
                  addFormatter(new SummaryJUnitResultFormatter());
              }
  
              Class testClass = Class.forName(junitTest.getName());
  
              try {
                  Method suiteMethod= testClass.getMethod("suite", new Class[0]);
                  suite = (Test)suiteMethod.invoke(null, new Class[0]);
              } catch(NoSuchMethodException e) {
              } catch(InvocationTargetException e) {
              } catch(IllegalAccessException e) {
              }
  
              if (suite == null) {
                  // try to extract a test suite automatically
                  // this will generate warnings if the class is no suitable Test
                  suite= new TestSuite(testClass);
              }
  
              res = new TestResult();
              res.addListener(this);
              for (int i=0; i < formatters.size(); i++) {
                  res.addListener((TestListener)formatters.elementAt(i));
              }
  
          } catch(Exception e) {
              retCode = 2;
  
              fireStartTestSuite();
              for (int i=0; i < formatters.size(); i++) {
                  ((TestListener)formatters.elementAt(i)).addError(null, e);
              }
              junitTest.setCounts(1, 0, 1);
              junitTest.setRunTime(0);
              fireEndTestSuite();
          }
      }
  
      public void run() {
          long start = System.currentTimeMillis();
  
          if (retCode != 0) { // had an exception in the constructor
              return;
          }
  
          fireStartTestSuite();
          suite.run(res);
          junitTest.setRunTime(System.currentTimeMillis()-start);
          junitTest.setCounts(res.runCount(), res.failureCount(),
                              res.errorCount());
          fireEndTestSuite();
  
          if (res.errorCount() != 0) {
              retCode = 2;
          } else if (res.failureCount() != 0) {
              retCode = 1;
          }
      }
  
      /**
       * Returns what System.exit() would return in the standalone version.
       *
       * @return 2 if errors occurred, 1 if tests failed else 0.
       */
      public int getRetCode() {
          return retCode;
      }
  
      /**
       * Interface TestListener.
       *
       * <p>A new Test is started.
       */
      public void startTest(Test t) {
          failed = false;
      }
  
      /**
       * Interface TestListener.
       *
       * <p>A Test is finished.
       */
      public void endTest(Test test) {
      }
  
      /**
       * Interface TestListener.
       *
       * <p>A Test failed.
       */
      public void addFailure(Test test, Throwable t) {
          failed = true;
  
          if (junitTest.getHaltonfailure()) {
              res.stop();
          }
      }
  
      /**
       * Interface TestListener.
       *
       * <p>An error occured while running the test.
       */
      public void addError(Test test, Throwable t) {
          failed = true;
  
          if (junitTest.getHaltonerror()) {
              res.stop();
          }
      }
  
      private void fireStartTestSuite() {
          for (int i=0; i<formatters.size(); i++) {
              ((JUnitResultFormatter)formatters.elementAt(i)).startTestSuite(junitTest);
          }
      }
  
      private void fireEndTestSuite() {
          for (int i=0; i<formatters.size(); i++) {
              ((JUnitResultFormatter)formatters.elementAt(i)).endTestSuite(junitTest);
          }
      }
  
      public void addFormatter(JUnitResultFormatter f) {
          formatters.addElement(f);
      }
  
      /**
       * Entry point for standalone (forked) mode.
       *
       * Parameters: testcaseclassname plus (up to) 6 parameters in the
       * format key=value.
       *
       * <table cols="3" border="1">
       * <tr><th>key</th><th>description</th><th>default value</th></tr>
       *
       * <tr><td>exit</td><td>exit with System.exit after testcase is
       * complete?</td><td>true</td></tr>
       *
       * <tr><td>haltOnError</td><td>halt test on
       * errors?</td><td>false</td></tr>
       *
       * <tr><td>haltOnFailure</td><td>halt test on
       * failures?</td><td>false</td></tr>
       *
       * <tr><td>printSummary</td><td>print summary to System.out?</td>
       * <td>true</td></tr>
       *
       * <tr><td>printXML</td><td>generate XML report?</td>
       * <td>false</td></tr>
       *
       * <tr><td>outfile</td><td>where to print the XML report - a
       * filename</td> <td>System.out</td></tr>
       *
       * </table>
       */
      public static void main(String[] args) throws IOException {
          boolean exitAtEnd = true;
          boolean haltError = false;
          boolean haltFail = false;
          boolean printSummary = true;
          boolean printXml = false;
          PrintWriter out = null;
  
          if (args.length == 0) {
              System.err.println("required argument TestClassName missing");
              if (exitAtEnd) {
                  System.exit(2);
              }
          } else {
  
              JUnitTest test = new JUnitTest();
              test.setName(args[0]);
              args[0] = null;
              test.setCommandline(args);
              JUnitTestRunner runner = new JUnitTestRunner(test);
              runner.run();
  
              if (exitAtEnd) {
                  System.exit(runner.getRetCode());
              }
          }
      }
  
  
      public static int runTest(JUnitTest test) {
          final JUnitTestRunner runner = new JUnitTestRunner(test);
          runner.run();
          return runner.getRetCode();
      }
  
  } // JUnitTestRunner
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java
  
  Index: SummaryJUnitResultFormatter.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.taskdefs.optional.junit;
  
  import java.text.NumberFormat;
  import junit.framework.Test;
  
  /**
   * Prints short summary output of the test to System.out
   *
   * @author <a href="mailto:stefan.bodewig@megabit.net">Stefan Bodewig</a>
   */
   
  public class SummaryJUnitResultFormatter implements JUnitResultFormatter {
  
      /**
       * Formatter for timings.
       */
      private NumberFormat nf = NumberFormat.getInstance();
  
      public SummaryJUnitResultFormatter() {
      }
  
      /**
       * The whole testsuite started.
       */
      public void startTestSuite(JUnitTest suite) {
      }
  
      /**
       * Interface TestListener.
       *
       * <p>A new Test is started.
       */
      public void startTest(Test t) {
      }
  
      /**
       * Interface TestListener.
       *
       * <p>A Test is finished.
       */
      public void endTest(Test test) {
      }
  
      /**
       * Interface TestListener.
       *
       * <p>A Test failed.
       */
      public void addFailure(Test test, Throwable t) {
      }
  
      /**
       * Interface TestListener.
       *
       * <p>An error occured while running the test.
       */
      public void addError(Test test, Throwable t) {
      }
  
      /**
       * The whole testsuite ended.
       */
      public void endTestSuite(JUnitTest suite) {
          System.out.print("Tests run: ");
          System.out.print(suite.runCount());
          System.out.print(", Failures: ");
          System.out.print(suite.failureCount());
          System.out.print(", Errors: ");
          System.out.print(suite.errorCount());
          System.out.print(", Time ellapsed: ");
          System.out.print(nf.format(suite.getRunTime()/1000.0));
          System.out.println(" sec");
      }
  }
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java
  
  Index: XMLJUnitResultFormatter.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.taskdefs.optional.junit;
  
  import java.io.PrintWriter;
  import java.io.StringWriter;
  import java.text.CharacterIterator;
  import java.text.NumberFormat;
  import java.text.StringCharacterIterator;
  import junit.framework.Test;
  import junit.framework.TestCase;
  
  /**
   * Prints XML output of the test to a specified Writer.
   *
   * @author <a href="mailto:stefan.bodewig@megabit.net">Stefan Bodewig</a>
   */
  
  public class XMLJUnitResultFormatter implements JUnitResultFormatter {
  
      /**
       * OutputStream for XML output.
       */
      private PrintWriter out;
      /**
       * Collects output during the test run.
       */
      private StringBuffer results = new StringBuffer();
      /**
       * platform independent line separator.
       */
      private static String newLine = System.getProperty("line.separator");
      /**
       * Formatter for timings.
       */
      private NumberFormat nf = NumberFormat.getInstance();
      /**
       * Timing helper.
       */
      private long lastTestStart = 0;
  
      public XMLJUnitResultFormatter(PrintWriter out) {
          this.out = out;
      }
  
      /**
       * The whole testsuite ended.
       */
      public void endTestSuite(JUnitTest suite) {
          out.println("<?xml version=\"1.0\"?>");
          out.print("<testsuite name=\"");
          out.print(suite.getName());
          out.print("\" tests=\"");
          out.print(suite.runCount());
          out.print("\" failures=\"");
          out.print(suite.failureCount());
          out.print("\" errors=\"");
          out.print(suite.errorCount());
          out.print("\" time=\"");
          out.print(nf.format(suite.getRunTime()/1000.0));
          out.println(" sec\">");
          out.print(results.toString());
          out.println("</testsuite>");
          out.flush();
          out.close();
      }
  
      /**
       * The whole testsuite started.
       */
      public void startTestSuite(JUnitTest suite) {
      }
  
      /**
       * Interface TestListener.
       *
       * <p>A new Test is started.
       */
      public void startTest(Test t) {
          lastTestStart = System.currentTimeMillis();
      }
  
      /**
       * Interface TestListener.
       *
       * <p>A Test is finished.
       */
      public void endTest(Test test) {
          formatTestCaseOpenTag(test);
          results.append("  </testcase>");
          results.append(newLine);
      }
  
      /**
       * Interface TestListener.
       *
       * <p>A Test failed.
       */
      public void addFailure(Test test, Throwable t) {
          formatError("failure", test, t);
      }
  
      /**
       * Interface TestListener.
       *
       * <p>An error occured while running the test.
       */
      public void addError(Test test, Throwable t) {
          formatError("error", test, t);
      }
  
      /**
       * Translates <, & and > to corresponding entities.
       */
      private String xmlEscape(String orig) {
          if (orig == null) return "";
          StringBuffer temp = new StringBuffer();
          StringCharacterIterator sci = new StringCharacterIterator(orig);
          for (char c = sci.first(); c != CharacterIterator.DONE;
               c = sci.next()) {
  
              switch (c) {
              case '<':
                  temp.append("&lt;");
                  break;
              case '>':
                  temp.append("&gt;");
                  break;
              case '&':
                  temp.append("&amp;");
                  break;
              default:
                  temp.append(c);
                  break;
              }
          }
          return temp.toString();
      }
  
      private void formatTestCaseOpenTag(Test test) {
          results.append("  <testcase");
          if (test != null && test instanceof TestCase) {
              results.append(" name=\"");
              results.append(((TestCase) test).name());
              results.append("\"");
          }
          results.append(" time=\"");
          results.append(nf.format((System.currentTimeMillis()-lastTestStart)
                                   / 1000.0));
          results.append("\">");
          results.append(newLine);
      }
  
      private void formatError(String type, Test test, Throwable t) {
          formatTestCaseOpenTag(test);
          results.append("    <");
          results.append(type);
          results.append(" message=\"");
          results.append(xmlEscape(t.getMessage()));
          results.append("\" type=\"");
          results.append(t.getClass().getName());
          results.append("\">");
          results.append(newLine);
  
          results.append("<![CDATA[");
          results.append(newLine);
          StringWriter swr = new StringWriter();
          t.printStackTrace(new PrintWriter(swr, true));
          results.append(swr.toString());
          results.append("]]>");
          results.append(newLine);
  
          results.append("    </");
          results.append(type);
          results.append(">");
          results.append(newLine);
  
          results.append("  </testcase>");
          results.append(newLine);
      }
  
  
  } // XMLJUnitResultFormatter
  
  
  

Re: cvs commit: jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/junit JUnitResultFormatter.java JUnitTask.java JUnitTest.java JUnitTestRunner.java SummaryJUnitResultFormatter.java XMLJUnitResultFormatter.java

Posted by Jeff Turner <je...@socialchange.net.au>.
Excellent :) I've always thought a JUnit taskdef would be cool.

--Jeff

AW: cvs commit: jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/junit JUnitResultFormatter.java JUnitTask.java JUnitTest.java JUnitTestRunner.java SummaryJUnitResultFormatter.java XMLJUnitResultFormatter.java

Posted by Wolfgang Werner <ww...@picturesafe.de>.
> [Stefan Bodewig]
>   Added:       src/main/org/apache/tools/ant/taskdefs/optional/junit
>                         JUnitResultFormatter.java JUnitTask.java
>                         JUnitTest.java JUnitTestRunner.java
>                         SummaryJUnitResultFormatter.java
>                         XMLJUnitResultFormatter.java

There it is! There it is! Great!
:^) 

Wolfgang