DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=4886>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=4886

JUnit task enhancement

           Summary: JUnit task enhancement
           Product: Ant
           Version: 1.4.1
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: Enhancement
          Priority: Other
         Component: Optional Tasks
        AssignedTo: [EMAIL PROTECTED]
        ReportedBy: [EMAIL PROTECTED]


I like to keep my build files as generic as possible, avoiding special cases for
singles files where possible. This works well for all tasks I use, except for
JUnit tasks, where you have to explicitly define which files (or classes) that
implement test cases.

This has been solved in some cases by separating the "test" source tree from the
"real" source tree and forcing test classes to certain name standards.

The problem with this is that there is a possibility for name clashes between
the trees, and that it is a bit cumbersome to find test classes for the working
classes. In fact - there is no way to see if a class or package has a test case
except for documentation.

Provided is a patch that implements a connection between source files and
package documentation files and their respective test classes. The patch uses a
javadoc tag (defaults to @testclass) that specifies which class that implements
a test case for the class or package that the javadoc describes.

Example:

/**
 * This is a nice class.
 * @author Erik Agsjo
 * @testclass com.noptec.some.Test
 */

Patches:

Index: src/main/org/apache/tools/ant/taskdefs/optional/junit/BatchTest.java
===================================================================
RCS file:
/home/cvspublic/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/junit/BatchTest.java,v
retrieving revision 1.8
diff -u -r1.8 BatchTest.java
--- src/main/org/apache/tools/ant/taskdefs/optional/junit/BatchTest.java        
2001/10/28 21:30:22     1.8
+++ src/main/org/apache/tools/ant/taskdefs/optional/junit/BatchTest.java        
2001/11/15 12:42:23
@@ -63,12 +63,17 @@
 import java.util.Enumeration;
 import java.util.Vector;
 import java.io.File;
+import java.io.FileReader;
+import java.io.BufferedReader;
 
 /**
- * <p> Create then run <code>JUnitTest</code>'s based on the list of files
given by the fileset attribute.
+ * <p> Create then run <code>JUnitTest</code>s based on the list of files given
by the fileset attribute.
  *
  * <p> Every <code>.java</code> or <code>.class</code> file in the fileset is 
- * assumed to be a testcase. 
+ * assumed to be a testcase unless the <code>usetag</code> attribute is 
specified.
+ * In that case, every <code>.java</code> or <code>.html</code> file in the 
fileset
+ * is parsed for a javadoc tag that specifies which testcase to run.
+ *
  * A <code>JUnitTest</code> is created for each of these named classes with
basic setup
  * inherited from the parent <code>BatchTest</code>.
  *
@@ -80,6 +85,15 @@
  */
 public final class BatchTest extends BaseTest {
 
+    /** are we scanning JavaDoc tags for test classes ? */
+    private boolean useTag = false;
+
+    /** standard JavaDoc tag that defines test classes */
+    static String DOCTAG_TEST = "testclass";
+
+    /** current JavaDoc tag that defines test classes */
+    private String tagName = DOCTAG_TEST;
+
     /** the reference to the project */
     private Project project;
 
@@ -95,6 +109,21 @@
     }
 
     /**
+     * enable / disable JavaDoc tag scanning
+     */
+    public void setUsetag(boolean status){
+
this.useTag = status;
+    }
+
+    /**
+     * set JavaDoc tag name to look for if "usetag" is enabled
+     * @param tagName the JavaDoc tag used to define test classes
+     */
+    public void setTagname(String tagName){
+
this.tagName = tagName;
+    }
+
+    /**
      * Add a new fileset instance to this batchtest. Whatever the fileset is,
      * only filename that are <tt>.java</tt> or <tt>.class</tt> will be
      * considered as 'candidates'.
@@ -130,16 +159,18 @@
 
     /**
      * Create all <tt>JUnitTest</tt>s based on the filesets. Each instance
-     * is configured to match this instance properties.
+     * is configured to match this instances properties.
      * @return the array of all <tt>JUnitTest</tt>s that belongs to this batch.
      */
     private JUnitTest[] createAllJUnitTest(){
         String[] filenames = getFilenames();
-        JUnitTest[] tests = new JUnitTest[filenames.length];
-        for (int i = 0; i < tests.length; i++) {
+
// hash set for eliminating duplicate test classes
+
HashSet uniqueTests = new HashSet();
+        for (int i = 0; i < filenames.length; i++) {
             String classname = javaToClass(filenames[i]);
-            tests[i] = createJUnitTest(classname);
+
    uniqueTests.add(createJUnitTest(classname));
         }
+
JUnitTest[] tests = (JUnitTest[]) uniqueTests.toArray(new JUnitTest[]{});
         return tests;
     }
 
@@ -164,10 +195,26 @@
             for (int k = 0; k < f.length; k++) {
                 String pathname = f[k];
                 if (pathname.endsWith(".java")) {
-                    v.addElement(pathname.substring(0,
pathname.length()-".java".length()));
+
            if (useTag){
+
                // parse javadoc tag from java source file
+
                String className = parseTestTag(tagName,
+
                                                ds.getBasedir() + 
File.separator + pathname,
+
                                                true);
+
                if(className != null){
+
                    v.addElement(className);
+
                }
+
            }else{
+
                v.addElement(pathname.substring(0, 
pathname.length()-".java".length()));
+
            }
                 } else if (pathname.endsWith(".class")) {
                     v.addElement(pathname.substring(0,
pathname.length()-".class".length()));
-                }
+                } else if (useTag && pathname.endsWith(".html")) {
+
            // parse javadoc tag from package doc file
+
            String className = parseTestTag(tagName, pathname, false);
+
            if(className != null){
+
                v.addElement(className);
+
            }
+
        }
             }
         }
 
@@ -185,6 +232,57 @@
      */
     public static final String javaToClass(String filename){
         return filename.replace(File.separatorChar, '.');
+    }
+
+    /**
+     * Simple, stupid, JavaDoc tag parser.
+     *
+     * @return the first word after the first matching tag in the file,
+     *         or null if no tag is found, or any other error occurs
+     * @param tagName the name of the tag to parse, with or without the
<code>@</code>-character
+     * @param fileName the full path to the file to parse
+     * @param prependPackage if set, the package of a parsed .java file will be
prepended to
+     *        the parsed tag value, if the tag does not look like a fully
specified class name
+     */
+    public static String parseTestTag(String tagName, String fileName, boolean
prependPackage){
+
String packageName = null;
+
+
if(!tagName.startsWith("@")){
+
    tagName = "@" + tagName;
+
}
+

+
try{
+
    BufferedReader reader = new BufferedReader(new FileReader(fileName));
+
    String line = null;
+
    while((line = reader.readLine()) != null){
+
        if(prependPackage && packageName == null && fileName.endsWith(".java")){
+
            if(line.trim().startsWith("package")){
+
                packageName = line.substring("package".length()).trim();
+
                if(packageName.endsWith(";")) {
+
                    packageName = packageName.substring(0, packageName.length() 
- 1).trim();
+
                }
+
            }
+
        }
+
        int tagIndex = line.indexOf(tagName);
+
        if(tagIndex != -1){
+
            StringTokenizer strtok = new 
StringTokenizer(line.substring(tagIndex +
tagName.length()));
+
            String className = null;
+
            try{
+
                className = strtok.nextToken();
+
            }catch(NoSuchElementException ex){
+
                continue;
+
            }
+
            return (prependPackage && className.indexOf(".") < 0 ?
+
                    packageName + "." + className : className);
+
        }
+
        
+
    }
+
}catch(java.io.FileNotFoundException fnf){
+
    // not gonna happen :)
+
}catch(java.io.IOException iox){
+
    // not gonna happen :)
+
}
+
return null;
     }
 
     /**


-----


Index: src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java
===================================================================
RCS file:
/home/cvspublic/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java,v
retrieving revision 1.8
diff -u -r1.8 JUnitTest.java
--- src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java        
2001/10/28 21:30:22     1.8
+++ src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java        
2001/11/15 12:42:34
@@ -186,4 +186,29 @@
             v.addElement( formatters.elementAt(i) );
         }
     }
+
+    /**
+     * Test class name based hash code implementation
+     */
+    public int hashCode(){
+
String name = getName();
+
if(name == null){
+
    return 0;
+
}else{
+
    return name.hashCode();
+
}
+    }
+
+    /**
+     * Two JUnitTest descendants of the same class with the same 
+     * containing test class are considered equal.
+     */
+    public boolean equals(Object other){
+
if(other != null && other.getClass().equals(getClass())){
+
    JUnitTest otherTest = (JUnitTest) other;
+
    return getName().equals(otherTest.getName());
+
}else{
+
    return false;
+
}
+    }
 }

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to