I have felt a need for a better link between a class and it's test case than what can be done in a build.xml.
I think it would be nice to see directly in a java file or package javadoc where the test case is.


Provided is a patch to BatchTest.java that makes it accept to new attributes "usetag" and "tagname".
When usetag is true, <batchtest> will scan the provided files for javadoc tag defined test cases.
Since this might result in duplicate test cases (several classes might specify the same test case),
duplicate tests are removed as well. For this to work I had to patch JUnitTest.java as well.


/Erik

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.7
diff -u -r1.7 JUnitTest.java
--- src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java        
2001/07/24 13:28:56     1.7
+++ src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java        
2001/09/19 12:44: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;
+       }
+    }
 }
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.7
diff -u -r1.7 BatchTest.java
--- src/main/org/apache/tools/ant/taskdefs/optional/junit/BatchTest.java        
2001/08/03 14:44:25     1.7
+++ src/main/org/apache/tools/ant/taskdefs/optional/junit/BatchTest.java        
2001/09/19 12:44:50
@@ -62,12 +62,17 @@
 
 import java.util.*;
 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>.
  *
@@ -79,6 +84,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;
 
@@ -94,6 +108,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'.
@@ -129,16 +158,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;
     }
 
@@ -163,10 +194,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);
+                   }
+               }
             }
         }
 
@@ -184,6 +231,57 @@
      */
     public final static 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;
     }
 
     /**

Reply via email to