ant-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Dominique Devienne <>
Subject RE: jpcoverage/junit intergration: how do I capture junit coverag e with with JProbe?
Date Tue, 16 Apr 2002 19:22:29 GMT

If I understood properly, you want a JUnit test suite that dynamically find
test cases. There's an open source such thing called testall (I don't know
where exactly if is at) which does that, but is limited to finding test from
the file-system (doesn't work with JARs), and it's pretty slow. I've rolled
up my own better alternative (IMHO) and asked my company to release it to
the wild, but was never given the green light.

Here's the class javadoc, and outline of the main method (without the
supporting classes unfortunately) which collects the test cases, and typical
ANT usage. Hopefully it should provide you with some ideas to implement your
own. Check out testall to see if it fits your need.

Regards, --DD

PS: I'm using reflection to find test cases now, but it would probably be
better to use BCEL.

import junit.framework.Test;
import junit.framework.TestSuite;

 * A JUnit test suite that scans a search path for tests classes
 * matching pre-determined criteria.
 * <p>
 * Search criteria include the following:
 * <ul>
 * <li><tt>searchpath</tt>: a classpath-like string of directories and/or
 *     JARs/ZIPs indicating where to look for test classes. If not defined,
 *     defaults to the current file-based URL of the system class
 * <li><tt>root</tt>: The root package the test classes must be to.
 *     for example, <tt>com.lgc.mowi</tt></li>
 * <li><tt>type</tt>: The type of unit test. Only classes inheriting from
 *     JUnit's <tt>Test</tt> class, which have a <tt>public static FINAL
 *     TEST_ALL_TEST_TYPE</tt> member whose value matches <tt>type</tt>
 *     considered valid tests.</li>
 * <li><tt>config</tt>: The declared configuration of this test run. This
 *     config will be compared to the required configuration of each test
 *     (declared by having a <tt>public static FINAL String
 *     </tt> member), and only tests with all there requirements satisfied
 *     are run.</li>
 * <li><tt>includes</tt>: An ANT-like pattern for classes. A typical pattern
 *     for unit test is <tt>**.test.*Test</tt>. Can also contain actual
 *     names, like in <tt>**.test.*Test, com.lgc.mowi.TestThis</tt>, which
 *     useful to include test classes with non-standard names.</li>
 * <li><tt>excludes</tt>: An ANT-like pattern for classes. Every test class
 *     included is checked against the <tt>excludes</tt> patterns.</li>
 * </ul>
 * <p>
 * The criteria listed above must be defined as Java system properties, with
 * the criterion name prefixed with <tt>testall.</tt>! In case this prefix
 * conflicts with something else, one can change it by specifying the
 * Java system properties.
 * <p>
 * Finally, one can use <tt>testall.verbose</tt> and <tt>testall.quiet</tt>
 * get more or no output to the console about the operation of this class.
 * By default, a little info is printed out, like the time it takes this
 * class to find all its tests classes.
 * <p>
 * Typical ANT usage:
 * <pre>
 * <target name="test" depends="classes">
 *   <property name="testcases" value="**.test.*Test" />
 *   <junit>
 *     <sysproperty key="testall.searchpath" value="${classes}" />
 *     <sysproperty key="testall.root"       value="com.lgc.mowi" />
 *     <sysproperty key="testall.type"       value="UNIT" />
 *     <sysproperty key="testall.config"     value="" />
 *     <sysproperty key="testall.includes"   value="${testcases}" />
 *     <sysproperty key="testall.excludes"   value="" />
 *     <test name="" />
 *   </junit>
 * </target>
 * </pre>
 * @author <a href="">Dominique Devienne</a>
 * @version Mar 2002 - Copyright (c) 2002, Landmark Graphics Corp.
public class DynamicTestSuite {

   * The method called by the JUnit framework.
   * @return a JUnit test suite of all the tests that matched
   *         the search criteria
  public static Test suite() {

    long start = System.currentTimeMillis();

    final TestSuite suite = new TestSuite();

    boolean usingSEARCHPATH = true;
    ClassPathScanner scanner = null;
    if (SEARCHPATH == null || SEARCHPATH.trim().length()==0) {
      usingSEARCHPATH = false;
      ClassLoader loader = ClassLoader.getSystemClassLoader();
      scanner = new ClassPathScanner(loader);
    else {
      URL[] urls = getURLs(SEARCHPATH);
      scanner = new ClassPathScanner(urls);

    if (ROOT != null) {
    ClassFilter filter1 = new ClassnameFilter(INCLUDES, EXCLUDES);
    ClassFilter filter2 = new TestTypeAndConfigFilter(TYPE, CONFIG);
    scanner.setFilter(new ClassFilter.AND(filter1, filter2));

    if (!QUIET) {
      String testType = (TYPE==null)?"": TYPE+" ";
      String scanWhat = (!usingSEARCHPATH)? "classpath": "searchpath";

      System.out.println("\nScanning "+scanWhat+" for

    if (VERBOSE) {
      System.out.println("      prefix = "+PREFIX);
      String scanWhat = (!usingSEARCHPATH)? "   classpath = ":
                                            "  searchpath = ";
      String searchpath = usingSEARCHPATH? SEARCHPATH:
      prettyPrintPath(searchpath, scanWhat, ";\n               ", "\n");
      System.out.println("        root = "+ROOT);
      System.out.println("        type = "+TYPE);
      System.out.println("      config = "+CONFIG);
      System.out.println("    includes = "+INCLUDES);
      System.out.println("    excludes = "+EXCLUDES);
      System.out.println("     verbose = "+VERBOSE);
      System.out.println("       quiet = "+QUIET);
      System.out.println("      noexec = "+NOEXEC);

    final int[] i = {0};
    scanner.scan(new ClassPathScanner.ClassProcessor() {
      public void process(String classname) {
        try {
          if (VERBOSE) {
            System.out.println("Adding "+classname);
          Class clazz = Class.forName(classname);
          if (!NOEXEC) {
        catch (ClassNotFoundException e) {
          if (VERBOSE) {
            System.out.println("WARNING: "+classname+" NOT FOUND!");

    if (!QUIET) {
      long duration = System.currentTimeMillis() - start;
      System.out.println("Found "+i[0]+" tests ("+duration+" ms)");

    return suite;

-----Original Message-----
From: Mohamed, Haneef [] 
Sent: Tuesday, April 16, 2002 1:44 PM
To: 'Ant Users List'
Subject: RE: jpcoverage/junit intergration: how do I capture junit coverag e
with with JProbe?

Thanks for the quick respons Gordon. I'll get busy with .reflection and post
my findings.


-----Original Message-----
From: Gordon Tyler []
Sent: Tuesday, April 16, 2002 2:29 PM
To: Ant Users List
Subject: Re: jpcoverage/junit intergration: how do I capture junit
coverage with with JProbe?

First, a disclaimer: I work at Sitraka (who produces JProbe) but I do not
work on JProbe itself. I am part of another team at Sitraka which merely
uses JProbe Coverage with JUnit tests. So I can't give support on JProbe.

We don't use the jpcoverage or junit tasks because of the limitations that
you've pointed out but rather we execute jplauncher.exe using an <exec> task
and pass all the appropriate command-line arguments. Also, we don't execute
TestRunner directly, but rather a class which we wrote that automatically
"discovers" all the test classes in our packages and builds a TestSuite
which it then runs using TestRunner.

Here's the <exec> task that we use:

<property name="coverage.home" value="${env.COVERAGE_HOME}"/>

<exec executable="${coverage.home}/jplauncher.exe">
        <arg value="-classpath"/>
        <arg value="YOUR_CLASSPATH_HERE"/>
        <arg value="-jp_function=coverage"/>
        <arg value="-jp_java_home=${java.home}"/>
        <arg value="-jp_java_exe=${java.home}/bin/java.exe"/>
        <arg value="-jp_vm=java2"/>
        <arg value="-jp_final_snapshot=coverage"/>
        <arg value="-jp_ignore_abstract=true"/>
        <arg value="-jp_record_from_start=coverage"/>
        <arg value="-jp_output_file=YOUR_OUTPUT_FILENAME_HERE"/>
        <arg value="-jp_snapshot_dir=YOUR_SNAPSHOT_DIRECTORY_HERE"/>
        <arg value="-jp_working_dir=YOUR_BUILD_WORKING_DIRECTORY_HERE"/>
        <arg value="com.acme.product.AutoTest"/>
        <arg value="-o"/>
        <arg value="YOUR_LOG_FILENAME_HERE"/>

The jp_working_dir option should point to a directory where your tests would
expect to be running from, so that they can find data files, etc. if
necessary. So in our case that would be our build/dist directory which
contains the jars and data files of our application.

The jp_filter option should be changed to use the correct includes and
excludes for your code.

com.acme.product.AutoTest is the fictional name of the "test discovery and
execution" class that I described earlier.

I don't actually use this myself, it's used by the QA guys on the team, so
I'm not 100% sure of how it all works ;) It's used in the context of a
nightly build where there isn't a human to observe it, so I don't think it
displays the Coverage UI.


----- Original Message -----
From: "Mohamed, Haneef" <>
To: <>
Sent: Tuesday, April 16, 2002 1:35 PM
Subject: jpcoverage/junit intergration: how do I capture junit coverage with
with JProbe?

> Hello everyone!
> Here is the problem I am encountering:
> Aim
> To run junit tests and capture code coverage metrics with jprobe as part
> the build process [pre-deployment]
> via ant

To unsubscribe, e-mail:   <>
For additional commands, e-mail: <>

To unsubscribe, e-mail:   <>
For additional commands, e-mail: <>

View raw message