/*******************************************************************************
* Copyright (c) 2006, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* David Saff (saff@mit.edu) - initial API and implementation
* (bug 102632: [JUnit] Support for JUnit 4.)
*******************************************************************************/
package org.eclipse.jdt.internal.junit.runner.junit3;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.eclipse.jdt.internal.junit.runner.FailuresFirstPrioritizer;
import org.eclipse.jdt.internal.junit.runner.ITestLoader;
import org.eclipse.jdt.internal.junit.runner.ITestPrioritizer;
import org.eclipse.jdt.internal.junit.runner.ITestReference;
import org.eclipse.jdt.internal.junit.runner.JUnitMessages;
import org.eclipse.jdt.internal.junit.runner.NullPrioritizer;
import org.eclipse.jdt.internal.junit.runner.RemoteTestRunner;
@SuppressWarnings({ "rawtypes", "unchecked" })
public class JUnit3TestLoader implements ITestLoader {
private static final String SUITE_METHODNAME = "suite"; //$NON-NLS-1$
private static final String SET_UP_TEST_METHOD_NAME = "setUpTest"; //$NON-NLS-1$
// WANT: give test loaders a schema
/*
* (non-Javadoc)
*
* @see org.eclipse.jdt.internal.junit.runner.TestLoader#loadSuites(java.lang.String[],
* java.lang.String, java.lang.String[],
* org.eclipse.jdt.internal.junit.runner.RunFailureListener,
* org.eclipse.jdt.internal.junit.runner.TestIdMap)
*/
public ITestReference[] loadTests(final Class[] testClasses, final String testName, final String[] failureNames,
final RemoteTestRunner listener) {
// instantiate all tests
ITestReference[] suites = new ITestReference[testClasses.length];
ITestPrioritizer prioritizer;
if (failureNames != null)
prioritizer = new FailuresFirstPrioritizer(failureNames);
else
prioritizer = new NullPrioritizer();
for (int i = 0; i < suites.length; i++) {
Class testClassName = testClasses[i];
Test test = getTest(testClassName, testName, listener);
prioritizer.prioritize(test);
suites[i] = new JUnit3TestReference(test);
}
return suites;
}
private Test createTest(final String testName, final Class testClass) {
Class[] classArgs = { String.class };
Test test;
Constructor constructor = null;
try {
try {
constructor = testClass.getConstructor(classArgs);
test = (Test) constructor.newInstance(new Object[] { testName });
} catch (NoSuchMethodException e) {
// try the no arg constructor supported in 3.8.1
constructor = testClass.getConstructor(new Class[0]);
test = (Test) constructor.newInstance(new Object[0]);
if (test instanceof TestCase)
((TestCase) test).setName(testName);
}
if (test != null)
return test;
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
} catch (NoSuchMethodException e) {
} catch (ClassCastException e) {
}
return warning("Could not create test \'" + testName + "\' "); //$NON-NLS-1$ //$NON-NLS-2$
}
public Test getTest(final Class testClass, final String testName, final RemoteTestRunner failureListener) {
if (testName != null) {
return setupTest(testClass, createTest(testName, testClass));
}
Method suiteMethod = null;
try {
suiteMethod = testClass.getMethod(JUnit3TestLoader.SUITE_METHODNAME, new Class[0]);
} catch (Exception e) {
// try to extract a test suite automatically
return new TestSuite(testClass);
}
if (!Modifier.isStatic(suiteMethod.getModifiers())) {
return warning(JUnitMessages.getString("RemoteTestRunner.error.suite.notstatic"));//$NON-NLS-1$
}
try {
Test test = (Test) suiteMethod.invoke(null, (Object[]) (new Class[0])); // static
if (test != null) {
return test;
}
return warning(JUnitMessages.getString("RemoteTestRunner.error.suite.nullreturn")); //$NON-NLS-1$
} catch (InvocationTargetException e) {
String message = JUnitMessages.getFormattedString("RemoteTestRunner.error.invoke", e.getTargetException().toString()); //$NON-NLS-1$
failureListener.runFailed(message, e);
return new TestSuite(testClass);
} catch (IllegalAccessException e) {
String message = JUnitMessages.getFormattedString("RemoteTestRunner.error.invoke", e.toString()); //$NON-NLS-1$
failureListener.runFailed(message, e);
return new TestSuite(testClass);
}
}
/**
* Prepare a single test to be run standalone. If the test case class provides a static method Test setUpTest(Test test) then this
* method will be invoked. Instead of calling the test method directly the "decorated" test returned from setUpTest will be called. The
* purpose of this mechanism is to enable tests which requires a set-up to be run individually.
*
* @param reloadedTestClass
* test class
* @param reloadedTest
* test instance
* @return the reloaded test, or the test wrapped with setUpTest(..) if available
*/
private Test setupTest(final Class reloadedTestClass, final Test reloadedTest) {
if (reloadedTestClass == null)
return reloadedTest;
Method setup = null;
try {
setup = reloadedTestClass.getMethod(SET_UP_TEST_METHOD_NAME, new Class[] { Test.class });
} catch (SecurityException e1) {
return reloadedTest;
} catch (NoSuchMethodException e) {
return reloadedTest;
}
if (setup.getReturnType() != Test.class)
return warning(JUnitMessages.getString("RemoteTestRunner.error.notestreturn")); //$NON-NLS-1$
if (!Modifier.isPublic(setup.getModifiers()))
return warning(JUnitMessages.getString("RemoteTestRunner.error.shouldbepublic")); //$NON-NLS-1$
if (!Modifier.isStatic(setup.getModifiers()))
return warning(JUnitMessages.getString("RemoteTestRunner.error.shouldbestatic")); //$NON-NLS-1$
try {
Test test = (Test) setup.invoke(null, new Object[] { reloadedTest });
if (test == null)
return warning(JUnitMessages.getString("RemoteTestRunner.error.nullreturn")); //$NON-NLS-1$
return test;
} catch (IllegalArgumentException e) {
return warning(JUnitMessages.getFormattedString("RemoteTestRunner.error.couldnotinvoke", e)); //$NON-NLS-1$
} catch (IllegalAccessException e) {
return warning(JUnitMessages.getFormattedString("RemoteTestRunner.error.couldnotinvoke", e)); //$NON-NLS-1$
} catch (InvocationTargetException e) {
return warning(JUnitMessages.getFormattedString("RemoteTestRunner.error.invocationexception", e.getTargetException())); //$NON-NLS-1$
}
}
/**
* @param message
* warning message
* @return a test which will fail and log a warning message.
*/
private Test warning(final String message) {
return new TestCase("warning") { //$NON-NLS-1$
@Override
protected void runTest() {
fail(message);
}
};
}
}