KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > displaytag > test > TestAll


1 package org.displaytag.test;
2
3 import java.io.File JavaDoc;
4 import java.lang.reflect.Method JavaDoc;
5 import java.lang.reflect.Modifier JavaDoc;
6 import java.net.URL JavaDoc;
7 import java.net.URLDecoder JavaDoc;
8 import java.util.ArrayList JavaDoc;
9 import java.util.Iterator JavaDoc;
10 import java.util.List JavaDoc;
11
12 import junit.framework.Test;
13 import junit.framework.TestCase;
14 import junit.framework.TestSuite;
15
16 import org.apache.commons.logging.Log;
17 import org.apache.commons.logging.LogFactory;
18
19
20 /**
21  * Dynamic test suite derived from http://www.javaworld.com/javaworld/jw-12-2000/jw-1221-junit.html. Runs all Java test
22  * cases in the source tree that extend TestCase. This helps running tests faster with ant/maven since httpunit tests
23  * requires forking and starting a new java process for each test is too slow.
24  * @author Fabrizio Giustina
25  * @version $Revision: 902 $ ($Author: fgiust $)
26  */

27 public class TestAll extends TestCase
28 {
29
30     /**
31      * Root package containing tests.
32      */

33     private static final String JavaDoc PACKAGE_ROOT = "org.displaytag";
34
35     /**
36      * logger.
37      */

38     private static Log log = LogFactory.getLog(TestAll.class);
39
40     /**
41      * Basic constructor - called by the test runners.
42      * @param name test name
43      */

44     public TestAll(String JavaDoc name)
45     {
46         super(name);
47     }
48
49     /**
50      * Iterates over the classes accessible via the iterator and adds them to the test suite.
51      * @param suite TestSuite empty test suite
52      * @param classIterator iterator on loaded classes
53      * @return int number of testcases added to suite
54      */

55     private static int addAllTests(TestSuite suite, Iterator JavaDoc classIterator)
56     {
57         int testClassCount = 0;
58         while (classIterator.hasNext())
59         {
60             Class JavaDoc testCaseClass = (Class JavaDoc) classIterator.next();
61
62             try
63             {
64                 Method JavaDoc suiteMethod = testCaseClass.getMethod("suite", new Class JavaDoc[0]);
65                 Test test = (Test) suiteMethod.invoke(null, new Class JavaDoc[0]); // static method
66
suite.addTest(test);
67             }
68             catch (NoSuchMethodException JavaDoc e)
69             {
70                 suite.addTest(new TestSuite(testCaseClass));
71             }
72             catch (Exception JavaDoc e)
73             {
74                 log.error("Failed to execute suite ()", e);
75             }
76             if (log.isDebugEnabled())
77             {
78                 log.debug("Loaded test case: " + testCaseClass.getName());
79             }
80             testClassCount++;
81         }
82         return testClassCount;
83     }
84
85     /**
86      * Dynamically create a test suite from a set of class files in a directory tree.
87      * @throws Throwable in running the suite() method
88      * @return TestSuite for all the found tests
89      */

90     public static Test suite() throws Throwable JavaDoc
91     {
92         try
93         {
94             String JavaDoc className = TestAll.class.getName();
95             URL JavaDoc testFile = TestAll.class.getResource("TestAll.class");
96             log.debug(testFile.getFile());
97             File JavaDoc classRoot = new File JavaDoc(URLDecoder.decode(testFile.getFile(), "UTF-8")).getParentFile();
98             while (className.indexOf(".") > -1)
99             {
100                 classRoot = classRoot.getParentFile();
101                 className = className.substring(className.indexOf(".") + 1, className.length());
102             }
103             log.debug("Looking for classes in " + classRoot);
104
105             ClassFinder classFinder = new ClassFinder(classRoot, PACKAGE_ROOT);
106             TestCaseLoader testCaseLoader = new TestCaseLoader();
107             testCaseLoader.loadTestCases(classFinder.getClasses());
108             TestSuite suite = new TestSuite();
109             int numberOfTests = addAllTests(suite, testCaseLoader.getClasses());
110             if (log.isDebugEnabled())
111             {
112                 log.debug("Number of test classes found: " + numberOfTests);
113             }
114             return suite;
115         }
116         catch (Throwable JavaDoc t)
117         {
118             // This ensures we have extra information.
119
// Otherwise all we get is a "Could not invoke the suite method." message.
120
log.error("suite()", t);
121             throw t;
122         }
123     }
124 }
125
126
127 /**
128  * This class is responsible for searching a directory for class files. It builds a list of fully qualified class names
129  * from the class files in the directory tree.
130  * @author Fabrizio Giustina
131  * @version $Revision: 902 $ ($Author: fgiust $)
132  */

133
134 class ClassFinder
135 {
136
137     /**
138      * List of found classes (names).
139      */

140     private List JavaDoc classNameList = new ArrayList JavaDoc();
141
142     /**
143      * length of the base package String.
144      */

145     private int startPackageLength;
146
147     /**
148      * Construct the class finder and locate all the classes in the directory structured pointed to by
149      * <code>classPathRoot</code>. Only classes in the package <code>packageRoot</code> are considered.
150      * @param classPathRoot classpath directory where to search for test cases
151      * @param packageRoot root package for tests to be included
152      */

153     public ClassFinder(File JavaDoc classPathRoot, String JavaDoc packageRoot)
154     {
155         startPackageLength = classPathRoot.getAbsolutePath().length() + 1;
156         String JavaDoc directoryOffset = packageRoot.replace('.', File.separatorChar);
157         findAndStoreTestClasses(new File JavaDoc(classPathRoot, directoryOffset));
158     }
159
160     /**
161      * Given a file name, guess the fully qualified class name.
162      * @param file class file
163      * @return class name
164      */

165     private String JavaDoc computeClassName(File JavaDoc file)
166     {
167         String JavaDoc absPath = file.getAbsolutePath();
168         String JavaDoc packageBase = absPath.substring(startPackageLength, absPath.length() - 6);
169         String JavaDoc className;
170         className = packageBase.replace(File.separatorChar, '.');
171         return className;
172     }
173
174     /**
175      * This method does all the work. It runs down the directory structure looking for java classes.
176      * @param currentDirectory directory to search class files in
177      */

178     private void findAndStoreTestClasses(File JavaDoc currentDirectory)
179     {
180         String JavaDoc[] files = currentDirectory.list();
181         for (int i = 0; i < files.length; i++)
182         {
183             File JavaDoc file = new File JavaDoc(currentDirectory, files[i]);
184             String JavaDoc fileBase = file.getName();
185             int idx = fileBase.indexOf(".class");
186             final int CLASS_EXTENSION_LENGTH = 6;
187
188             if (idx != -1 && (fileBase.length() - idx) == CLASS_EXTENSION_LENGTH)
189             {
190                 String JavaDoc className = computeClassName(file);
191                 classNameList.add(className);
192             }
193             else
194             {
195                 if (file.isDirectory())
196                 {
197                     findAndStoreTestClasses(file);
198                 }
199             }
200         }
201     }
202
203     /**
204      * Return the found classes.
205      * @return Iterator on classes names
206      */

207     public Iterator JavaDoc getClasses()
208     {
209         return classNameList.iterator();
210     }
211 }
212
213
214 /**
215  * Responsible for loading classes representing valid test cases.
216  * @author Fabrizio Giustina
217  * @version $Revision: 902 $ ($Author: fgiust $)
218  */

219
220 class TestCaseLoader
221 {
222
223     /**
224      * list containing laded classes.
225      */

226     private List JavaDoc classList = new ArrayList JavaDoc();
227
228     /**
229      * Load the classes that represent test cases we are interested.
230      * @param classNamesIterator An iterator over a collection of fully qualified class names
231      */

232     public void loadTestCases(Iterator JavaDoc classNamesIterator)
233     {
234         while (classNamesIterator.hasNext())
235         {
236             String JavaDoc className = (String JavaDoc) classNamesIterator.next();
237             try
238             {
239                 Class JavaDoc candidateClass = Class.forName(className);
240                 addClassIfTestCase(candidateClass);
241             }
242             catch (ClassNotFoundException JavaDoc e)
243             {
244                 System.err.println("Cannot load class: " + className + " " + e.getMessage());
245             }
246             catch (NoClassDefFoundError JavaDoc e)
247             {
248                 System.err.println("Cannot load class that " + className + " is dependant on");
249             }
250         }
251     }
252
253     /**
254      * Adds testCaseClass to the list of classes if the class extends TestCase and it's not abstract.
255      * @param testCaseClass class to test
256      */

257     private void addClassIfTestCase(Class JavaDoc testCaseClass)
258     {
259         if (TestCase.class.isAssignableFrom(testCaseClass)
260             && !TestAll.class.isAssignableFrom(testCaseClass)
261             && !Modifier.isAbstract(testCaseClass.getModifiers()))
262         {
263             classList.add(testCaseClass);
264         }
265     }
266
267     /**
268      * Obtain an iterator over the collection of test case classes loaded by <code>loadTestCases</code>.
269      * @return Iterator on loaded classes list
270      */

271     public Iterator JavaDoc getClasses()
272     {
273         return classList.iterator();
274     }
275 }
Popular Tags