/*
* Copyright 2001-2008 Geert Bevin <gbevin[remove] at uwyn dot com>
* Licensed under the Apache License, Version 2.0 (the "License")
* $Id: ParametrizedTestSuite.java 3918 2008-04-14 17:35:35Z gbevin $
*/
package com.uwyn.rife;
import com.uwyn.rife.tools.ExceptionUtils;
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.Vector;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
public class ParametrizedTestSuite extends TestSuite
{
public ParametrizedTestSuite(String name)
{
super(name);
}
public ParametrizedTestSuite(final Class theClass, Class[] argsTypes, ArrayList<Object[]> argsList)
{
super(theClass.getName());
initParametrization(theClass, argsTypes, argsList);
}
protected void initParametrization(final Class theClass, Class[] argsTypes, ArrayList<Object[]> argsList)
{
Constructor constructor = null;
try
{
constructor = getParametrizedConstructor(theClass, argsTypes);
}
catch (NoSuchMethodException e)
{
addTest(parametrizationWarning("Class " + theClass.getName() + " has no public constructor that fits."));
return;
}
if (!Modifier.isPublic(theClass.getModifiers()))
{
addTest(parametrizationWarning("Class " + theClass.getName() + " is not public."));
return;
}
Class superClass = theClass;
Vector<String> names = new Vector<String>();
while (Test.class.isAssignableFrom(superClass))
{
Method[] methods = superClass.getDeclaredMethods();
for (int i = 0; i < methods.length; i++)
{
addParametrizedTestMethod(methods[i], names, constructor, argsList);
}
superClass = superClass.getSuperclass();
}
if (countTestCases() == 0)
{
addTest(parametrizationWarning("No tests found in " + theClass.getName()));
}
}
protected Constructor getParametrizedConstructor(Class theClass, Class[] argsTypes)
throws NoSuchMethodException
{
return theClass.getConstructor(argsTypes);
}
protected Test parametrizationWarning(final String message)
{
return new TestCase("warning")
{
protected void runTest()
{
fail(message);
}
};
}
protected void addParametrizedTestMethod(Method m, Vector<String> names, Constructor constructor, ArrayList<Object[]> argsList)
{
String name = m.getName();
if (names.contains(name))
{
return;
}
if (isPublicTestMethod(m))
{
names.addElement(name);
Object test = null;
for (Object[] args : argsList)
{
args[args.length-1] = name;
try
{
test = constructor.newInstance(args);
if (test instanceof Test)
{
addTest((Test)test);
}
else
{
addTest(parametrizationWarning("Cannot instantiate test case: " + name + " (is no instance of Test but of " + test.getClass().getName() + ")"));
}
}
catch (InstantiationException e)
{
addTest(parametrizationWarning("Cannot instantiate test case: " + name + " (" + ExceptionUtils.getExceptionStackTrace(e) + ")"));
}
catch (InvocationTargetException e)
{
addTest(parametrizationWarning("Exception in constructor: " + name + " (" + ExceptionUtils.getExceptionStackTrace(e.getTargetException()) + ")"));
}
catch (IllegalAccessException e)
{
addTest(parametrizationWarning("Cannot access test case: " + name + " (" + ExceptionUtils.getExceptionStackTrace(e) + ")"));
}
}
}
else
{
// almost a test method
if (isTestMethod(m))
{
addTest(parametrizationWarning("Test method isn't public: " + m.getName()));
}
}
}
protected boolean isPublicTestMethod(Method m)
{
return isTestMethod(m) && Modifier.isPublic(m.getModifiers());
}
protected boolean isTestMethod(Method m)
{
String name = m.getName();
Class[] parameters = m.getParameterTypes();
Class returnType = m.getReturnType();
return parameters.length == 0 && name.startsWith("test") && returnType.equals(Void.TYPE);
}
}