ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bugzi...@apache.org
Subject DO NOT REPLY [Bug 4886] New: - JUnit task enhancement
Date Thu, 15 Nov 2001 12:59:32 GMT
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: ant-dev@jakarta.apache.org
        ReportedBy: erik.agsjo@noptec.com


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:ant-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:ant-dev-help@jakarta.apache.org>


Mime
View raw message