001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.tools.ant.taskdefs.optional.junit;
020:
021: import java.io.File;
022: import java.util.Enumeration;
023: import java.util.Iterator;
024: import java.util.Vector;
025: import org.apache.tools.ant.Project;
026: import org.apache.tools.ant.types.FileSet;
027: import org.apache.tools.ant.types.Resource;
028: import org.apache.tools.ant.types.ResourceCollection;
029: import org.apache.tools.ant.types.resources.Resources;
030:
031: /**
032: * <p> Create then run <code>JUnitTest</code>'s based on the list of files
033: * given by the fileset attribute.
034: *
035: * <p> Every <code>.java</code> or <code>.class</code> file in the fileset is
036: * assumed to be a testcase.
037: * A <code>JUnitTest</code> is created for each of these named classes with
038: * basic setup inherited from the parent <code>BatchTest</code>.
039: *
040: * @see JUnitTest
041: */
042: public final class BatchTest extends BaseTest {
043:
044: /** the reference to the project */
045: private Project project;
046:
047: /** the list of filesets containing the testcase filename rules */
048: private Resources resources = new Resources();
049:
050: /**
051: * create a new batchtest instance
052: * @param project the project it depends on.
053: */
054: public BatchTest(Project project) {
055: this .project = project;
056: }
057:
058: /**
059: * Add a new fileset instance to this batchtest. Whatever the fileset is,
060: * only filename that are <tt>.java</tt> or <tt>.class</tt> will be
061: * considered as 'candidates'.
062: * @param fs the new fileset containing the rules to get the testcases.
063: */
064: public void addFileSet(FileSet fs) {
065: add(fs);
066:
067: // this one is here because the changes to support ResourceCollections
068: // have broken Magic's JUnitTestTask.
069: //
070: // The task adds a FileSet to a BatchTest instance using the
071: // Java API and without telling the FileSet about its project
072: // instance. The original code would pass in project on the
073: // call to getDirectoryScanner - which is now hidden deep into
074: // Resources.iterator() and not reachable.
075: if (fs.getProject() == null) {
076: fs.setProject(project);
077: }
078: }
079:
080: /**
081: * Add a new ResourceCollection instance to this
082: * batchtest. Whatever the collection is, only names that are
083: * <tt>.java</tt> or <tt>.class</tt> will be considered as
084: * 'candidates'.
085: * @param rc the new ResourceCollection containing the rules to
086: * get the testcases.
087: * @since Ant 1.7
088: */
089: public void add(ResourceCollection rc) {
090: resources.add(rc);
091: }
092:
093: /**
094: * Return all <tt>JUnitTest</tt> instances obtain by applying the fileset rules.
095: * @return an enumeration of all elements of this batchtest that are
096: * a <tt>JUnitTest</tt> instance.
097: */
098: public Enumeration elements() {
099: JUnitTest[] tests = createAllJUnitTest();
100: return Enumerations.fromArray(tests);
101: }
102:
103: /**
104: * Convenient method to merge the <tt>JUnitTest</tt>s of this batchtest
105: * to a <tt>Vector</tt>.
106: * @param v the vector to which should be added all individual tests of this
107: * batch test.
108: */
109: void addTestsTo(Vector v) {
110: JUnitTest[] tests = createAllJUnitTest();
111: v.ensureCapacity(v.size() + tests.length);
112: for (int i = 0; i < tests.length; i++) {
113: v.addElement(tests[i]);
114: }
115: }
116:
117: /**
118: * Create all <tt>JUnitTest</tt>s based on the filesets. Each instance
119: * is configured to match this instance properties.
120: * @return the array of all <tt>JUnitTest</tt>s that belongs to this batch.
121: */
122: private JUnitTest[] createAllJUnitTest() {
123: String[] filenames = getFilenames();
124: JUnitTest[] tests = new JUnitTest[filenames.length];
125: for (int i = 0; i < tests.length; i++) {
126: String classname = javaToClass(filenames[i]);
127: tests[i] = createJUnitTest(classname);
128: }
129: return tests;
130: }
131:
132: /**
133: * Iterate over all filesets and return the filename of all files
134: * that end with <tt>.java</tt> or <tt>.class</tt>. This is to avoid
135: * wrapping a <tt>JUnitTest</tt> over an xml file for example. A Testcase
136: * is obviously a java file (compiled or not).
137: * @return an array of filenames without their extension. As they should
138: * normally be taken from their root, filenames should match their fully
139: * qualified class name (If it is not the case it will fail when running the test).
140: * For the class <tt>org/apache/Whatever.class</tt> it will return <tt>org/apache/Whatever</tt>.
141: */
142: private String[] getFilenames() {
143: Vector v = new Vector();
144: Iterator iter = resources.iterator();
145: while (iter.hasNext()) {
146: Resource r = (Resource) iter.next();
147: if (r.isExists()) {
148: String pathname = r.getName();
149: if (pathname.endsWith(".java")) {
150: v.addElement(pathname.substring(0, pathname
151: .length()
152: - ".java".length()));
153: } else if (pathname.endsWith(".class")) {
154: v.addElement(pathname.substring(0, pathname
155: .length()
156: - ".class".length()));
157: }
158: }
159: }
160:
161: String[] files = new String[v.size()];
162: v.copyInto(files);
163: return files;
164: }
165:
166: /**
167: * Convenient method to convert a pathname without extension to a
168: * fully qualified classname. For example <tt>org/apache/Whatever</tt> will
169: * be converted to <tt>org.apache.Whatever</tt>
170: * @param filename the filename to "convert" to a classname.
171: * @return the classname matching the filename.
172: */
173: public static String javaToClass(String filename) {
174: return filename.replace(File.separatorChar, '.').replace('/',
175: '.').replace('\\', '.');
176: }
177:
178: /**
179: * Create a <tt>JUnitTest</tt> that has the same property as this
180: * <tt>BatchTest</tt> instance.
181: * @param classname the name of the class that should be run as a
182: * <tt>JUnitTest</tt>. It must be a fully qualified name.
183: * @return the <tt>JUnitTest</tt> over the given classname.
184: */
185: private JUnitTest createJUnitTest(String classname) {
186: JUnitTest test = new JUnitTest();
187: test.setName(classname);
188: test.setHaltonerror(this .haltOnError);
189: test.setHaltonfailure(this .haltOnFail);
190: test.setFiltertrace(this .filtertrace);
191: test.setFork(this .fork);
192: test.setIf(this .ifProperty);
193: test.setUnless(this .unlessProperty);
194: test.setTodir(this .destDir);
195: test.setFailureProperty(failureProperty);
196: test.setErrorProperty(errorProperty);
197: Enumeration list = this .formatters.elements();
198: while (list.hasMoreElements()) {
199: test.addFormatter((FormatterElement) list.nextElement());
200: }
201: return test;
202: }
203:
204: }
|