|
What this is
Other links
The source code/* * Copyright 2001-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.collections; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import junit.framework.TestCase; import junit.framework.TestSuite; /** * A {@link TestCase} that can define both simple and bulk test methods. *
null from the bulk test method. If you only
* want to override specific simple tests within a bulk test, use the
* {@link #ignoredTests} method.
*
* Note that if you want to use the bulk test methods, you must
* define your
*
* @return a clone of this
*
* If a test that's defined by this
*
* A test's name is formed by taking the class name of the
* root * TestHashMap.bulkTestEntrySet.testClear ** * is the name of one of the simple tests defined in the sample classes * described above. If the sample TestHashMap class
* included this method:
*
* * public String[] ignoredTests() { * return new String[] { "TestHashMap.bulkTestEntrySet.testClear" }; * } ** * then the entry set's clear method wouldn't be tested, but the key * set's clear method would. * * @return an array of the names of tests to ignore, or null if * no tests should be ignored */ public String[] ignoredTests() { return null; } /** * Returns the display name of this BulkTest .
*
* @return the display name of this BulkTest
*/
public String toString() {
return getName() + "(" + verboseName + ") ";
}
/**
* Returns a {@link TestSuite} for testing all of the simple tests
* and all the bulk tests defined by the given class.* * The class is examined for simple and bulk test methods; any child * bulk tests are also examined recursively; and the results are stored * in a hierarchal {@link TestSuite}.
*
* The given class must be a subclass of * * @param c the class to examine for simple and bulk tests * @return a {@link TestSuite} containing all the simple and bulk tests * defined by that class */ public static TestSuite makeSuite(Class c) { if (Modifier.isAbstract(c.getModifiers())) { throw new IllegalArgumentException("Class must not be abstract."); } if (!BulkTest.class.isAssignableFrom(c)) { throw new IllegalArgumentException("Class must extend BulkTest."); } return new BulkTestSuiteMaker(c).make(); } } // It was easier to use a separate class to do all the reflection stuff // for making the TestSuite instances. Having permanent state around makes // it easier to handle the recursion. class BulkTestSuiteMaker { /** The class that defines simple and bulk tests methods. */ private Class startingClass; /** List of ignored simple test names. */ private List ignored; /** The TestSuite we're currently populating. Can change over time. */ private TestSuite result; /** * The prefix for simple test methods. Used to check if a test is in * the ignored list. */ private String prefix; /** * Constructor. * * @param startingClass the starting class */ public BulkTestSuiteMaker(Class startingClass) { this.startingClass = startingClass; } /** * Makes a hierarchal TestSuite based on the starting class. * * @return the hierarchal TestSuite for startingClass */ public TestSuite make() { this.result = new TestSuite(); this.prefix = getBaseName(startingClass); result.setName(prefix); BulkTest bulk = makeFirstTestCase(startingClass); ignored = new ArrayList(); String[] s = bulk.ignoredTests(); if (s != null) { ignored.addAll(Arrays.asList(s)); } make(bulk); return result; } /** * Appends all the simple tests and bulk tests defined by the given * instance's class to the current TestSuite. * * @param bulk An instance of the class that defines simple and bulk * tests for us to append */ void make(BulkTest bulk) { Class c = bulk.getClass(); Method[] all = c.getMethods(); for (int i = 0; i < all.length; i++) { if (isTest(all[i])) addTest(bulk, all[i]); if (isBulk(all[i])) addBulk(bulk, all[i]); } } /** * Adds the simple test defined by the given method to the TestSuite. * * @param bulk The instance of the class that defined the method * (I know it's weird. But the point is, we can clone the instance * and not have to worry about constructors.) * @param m The simple test method */ void addTest(BulkTest bulk, Method m) { BulkTest bulk2 = (BulkTest)bulk.clone(); bulk2.setName(m.getName()); bulk2.verboseName = prefix + "." + m.getName(); if (ignored.contains(bulk2.verboseName)) return; result.addTest(bulk2); } /** * Adds a whole new suite of tests that are defined by the result of * the given bulk test method. In other words, the given bulk test * method is invoked, and the resulting BulkTest instance is examined * for yet more simple and bulk tests. * * @param bulk The instance of the class that defined the method * @param m The bulk test method */ void addBulk(BulkTest bulk, Method m) { String verboseName = prefix + "." + m.getName(); if (ignored.contains(verboseName)) return; BulkTest bulk2; try { bulk2 = (BulkTest)m.invoke(bulk, null); if (bulk2 == null) return; } catch (InvocationTargetException ex) { ex.getTargetException().printStackTrace(); throw new Error(); // FIXME; } catch (IllegalAccessException ex) { ex.printStackTrace(); throw new Error(); // FIXME; } // Save current state on the stack. String oldPrefix = prefix; TestSuite oldResult = result; prefix = prefix + "." + m.getName(); result = new TestSuite(); result.setName(m.getName()); make(bulk2); oldResult.addTest(result); // Restore the old state prefix = oldPrefix; result = oldResult; } /** * Returns the base name of the given class. * * @param c the class * @return the name of that class, minus any package names */ private static String getBaseName(Class c) { String name = c.getName(); int p = name.lastIndexOf('.'); if (p > 0) { name = name.substring(p + 1); } return name; } // These three methods are used to create a valid BulkTest instance // from a class. private static Constructor getTestCaseConstructor(Class c) { try { return c.getConstructor(new Class[] { String.class }); } catch (NoSuchMethodException e) { throw new IllegalArgumentException(c + " must provide " + "a (String) constructor"); } } private static BulkTest makeTestCase(Class c, Method m) { Constructor con = getTestCaseConstructor(c); try { return (BulkTest)con.newInstance(new String[] { m.getName() }); } catch (InvocationTargetException e) { e.printStackTrace(); throw new RuntimeException(); // FIXME; } catch (IllegalAccessException e) { throw new Error(); // should never occur } catch (InstantiationException e) { throw new RuntimeException(); // FIXME; } } private static BulkTest makeFirstTestCase(Class c) { Method[] all = c.getMethods(); for (int i = 0; i < all.length; i++) { if (isTest(all[i])) return makeTestCase(c, all[i]); } throw new IllegalArgumentException(c.getName() + " must provide " + " at least one test method."); } /** * Returns true if the given method is a simple test method. */ private static boolean isTest(Method m) { if (!m.getName().startsWith("test")) return false; if (m.getReturnType() != Void.TYPE) return false; if (m.getParameterTypes().length != 0) return false; int mods = m.getModifiers(); if (Modifier.isStatic(mods)) return false; if (Modifier.isAbstract(mods)) return false; return true; } /** * Returns true if the given method is a bulk test method. */ private static boolean isBulk(Method m) { if (!m.getName().startsWith("bulkTest")) return false; if (m.getReturnType() != BulkTest.class) return false; if (m.getParameterTypes().length != 0) return false; int mods = m.getModifiers(); if (Modifier.isStatic(mods)) return false; if (Modifier.isAbstract(mods)) return false; return true; } } |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.