CVS: junit/src/org/junit/internal/runners TestClass.java, NONE, 1.1 MethodRoadie.java, NONE, 1.1 JUnit38ClassRunner.java, NONE, 1.1 TestMethod.java, 1.2, 1.3 JUnit4ClassRunner.java, NONE, 1.1 FailedBefore.java, NONE, 1.1 ClassRoadie.java, NONE, 1.1 CompositeRunner.java, 1.2, 1.3 MethodValidator.java, 1.4, 1.5 TestIntrospector.java, 1.4, NONE TextListener.java, 1.1, NONE TestClassRunner.java, 1.3, NONE TestClassMethodsRunner.java, 1.4, NONE OldTestClassRunner.java, 1.4, NONE TestMethodRunner.java, 1.3, NONE BeforeAndAfterRunner.java, 1.3, NONE
David Saff <[email protected]> Tue, 20 Mar 2007 07:43:53 -0700
| Newsgroups | gmane.comp.java.junit.devel |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/junit/junit/src/org/junit/internal/runners
In directory sc8-pr-cvs6.sourceforge.net:/tmp/cvs-serv30152/src/org/junit/internal/runners
Modified Files:
CompositeRunner.java MethodValidator.java
Added Files:
TestClass.java MethodRoadie.java JUnit38ClassRunner.java
TestMethod.java JUnit4ClassRunner.java FailedBefore.java
ClassRoadie.java
Removed Files:
TestIntrospector.java TextListener.java TestClassRunner.java
TestClassMethodsRunner.java OldTestClassRunner.java
TestMethodRunner.java BeforeAndAfterRunner.java
Log Message:
Runner rearchitecting to begin 4.4 development
--- NEW FILE: TestClass.java ---
package org.junit.internal.runners;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class TestClass {
private final Class<?> fClass;
public TestClass(Class<?> klass) {
fClass= klass;
}
List<Method> getTestMethods() {
return getAnnotatedMethods(Test.class);
}
public List<Method> getBefores() {
return getAnnotatedMethods(BeforeClass.class);
}
public List<Method> getAfters() {
return getAnnotatedMethods(AfterClass.class);
}
public List<Method> getAnnotatedMethods(Class<? extends Annotation> annotationClass) {
List<Method> results= new ArrayList<Method>();
for (Class<?> eachClass : getSuperClasses(fClass)) {
Method[] methods= eachClass.getDeclaredMethods();
for (Method eachMethod : methods) {
Annotation annotation= eachMethod.getAnnotation(annotationClass);
if (annotation != null && ! isShadowed(eachMethod, results))
results.add(eachMethod);
}
}
if (runsTopToBottom(annotationClass))
Collections.reverse(results);
return results;
}
private boolean runsTopToBottom(Class< ? extends Annotation> annotation) {
return annotation.equals(Before.class) || annotation.equals(BeforeClass.class);
}
private boolean isShadowed(Method method, List<Method> results) {
for (Method each : results) {
if (isShadowed(method, each))
return true;
}
return false;
}
private boolean isShadowed(Method current, Method previous) {
if (! previous.getName().equals(current.getName()))
return false;
if (previous.getParameterTypes().length != current.getParameterTypes().length)
return false;
for (int i= 0; i < previous.getParameterTypes().length; i++) {
if (! previous.getParameterTypes()[i].equals(current.getParameterTypes()[i]))
return false;
}
return true;
}
private List<Class<?>> getSuperClasses(Class< ?> testClass) {
ArrayList<Class<?>> results= new ArrayList<Class<?>>();
Class<?> current= testClass;
while (current != null) {
results.add(current);
current= current.getSuperclass();
}
return results;
}
public Constructor<?> getConstructor() throws SecurityException, NoSuchMethodException {
return fClass.getConstructor();
}
public Class<?> getJavaClass() {
return fClass;
}
public String getName() {
return fClass.getName();
}
}
--- NEW FILE: MethodRoadie.java ---
package org.junit.internal.runners;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.junit.runner.Description;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunNotifier;
public class MethodRoadie {
private final Object fTest;
private final Method fMethod;
private final RunNotifier fNotifier;
private final Description fDescription;
private TestMethod fTestMethod;
public MethodRoadie(Object test, Method method, RunNotifier notifier, Description description, TestClass testClass) {
fTest= test;
fMethod= method;
fNotifier= notifier;
fDescription= description;
fTestMethod= new TestMethod(method, testClass);
}
public void run() {
if (fTestMethod.isIgnored()) {
fNotifier.fireTestIgnored(fDescription);
return;
}
fNotifier.fireTestStarted(fDescription);
try {
long timeout= fTestMethod.getTimeout();
if (timeout > 0)
runWithTimeout(timeout);
else
runTest();
} finally {
fNotifier.fireTestFinished(fDescription);
}
}
private void runWithTimeout(long timeout) {
ExecutorService service= Executors.newSingleThreadExecutor();
Callable<Object> callable= new Callable<Object>() {
public Object call() throws Exception {
runTest();
return null;
}
};
Future<Object> result= service.submit(callable);
service.shutdown();
try {
boolean terminated= service.awaitTermination(timeout,
TimeUnit.MILLISECONDS);
if (!terminated)
service.shutdownNow();
result.get(0, TimeUnit.MILLISECONDS); // throws the exception if one occurred during the invocation
} catch (TimeoutException e) {
addFailure(new Exception(String.format("test timed out after %d milliseconds", timeout)));
} catch (Exception e) {
addFailure(e);
}
}
public void runTest() {
try {
runBefores();
runTestMethod();
} catch (FailedBefore e) {
} finally {
runAfters();
}
}
protected void runTestMethod() {
try {
fMethod.invoke(fTest);
if (fTestMethod.expectsException())
addFailure(new AssertionError("Expected exception: " + fTestMethod.getExpectedException().getName()));
} catch (InvocationTargetException e) {
Throwable actual= e.getTargetException();
if (!fTestMethod.expectsException())
addFailure(actual);
else if (fTestMethod.isUnexpected(actual)) {
String message= "Unexpected exception, expected<" + fTestMethod.getExpectedException().getName() + "> but was<"
+ actual.getClass().getName() + ">";
addFailure(new Exception(message, actual));
}
} catch (Throwable e) {
addFailure(e);
}
}
private void runBefores() throws FailedBefore {
try {
List<Method> befores= fTestMethod.getBefores();
for (Method before : befores)
before.invoke(fTest);
} catch (InvocationTargetException e) {
addFailure(e.getTargetException());
throw new FailedBefore();
} catch (Throwable e) {
addFailure(e);
throw new FailedBefore();
}
}
private void runAfters() {
List<Method> afters= fTestMethod.getAfters();
for (Method after : afters)
try {
after.invoke(fTest);
} catch (InvocationTargetException e) {
addFailure(e.getTargetException());
} catch (Throwable e) {
addFailure(e); // Untested, but seems impossible
}
}
protected void addFailure(Throwable e) {
fNotifier.fireTestFailure(new Failure(fDescription, e));
}
}
--- NEW FILE: JUnit38ClassRunner.java ---
package org.junit.internal.runners;
import junit.extensions.TestDecorator;
import junit.framework.AssertionFailedError;
import junit.framework.JUnit4TestAdapter;
import junit.framework.JUnit4TestCaseFacade;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestListener;
import junit.framework.TestResult;
import junit.framework.TestSuite;
import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunNotifier;
public class JUnit38ClassRunner extends Runner {
private static final class OldTestClassAdaptingListener implements
TestListener {
private final RunNotifier fNotifier;
private OldTestClassAdaptingListener(RunNotifier notifier) {
fNotifier= notifier;
}
public void endTest(Test test) {
fNotifier.fireTestFinished(asDescription(test));
}
public void startTest(Test test) {
fNotifier.fireTestStarted(asDescription(test));
}
// Implement junit.framework.TestListener
public void addError(Test test, Throwable t) {
Failure failure= new Failure(asDescription(test), t);
fNotifier.fireTestFailure(failure);
}
private Description asDescription(Test test) {
if (test instanceof JUnit4TestCaseFacade) {
JUnit4TestCaseFacade facade= (JUnit4TestCaseFacade) test;
return facade.getDescription();
}
return Description.createTestDescription(test.getClass(), getName(test));
}
private String getName(Test test) {
if (test instanceof TestCase)
return ((TestCase) test).getName();
else
return test.toString();
}
public void addFailure(Test test, AssertionFailedError t) {
addError(test, t);
}
}
private Test fTest;
@SuppressWarnings("unchecked")
public JUnit38ClassRunner(Class<?> klass) {
this(new TestSuite(klass.asSubclass(TestCase.class)));
}
public JUnit38ClassRunner(Test test) {
super();
fTest= test;
}
@Override
public void run(RunNotifier notifier) {
TestResult result= new TestResult();
result.addListener(createAdaptingListener(notifier));
fTest.run(result);
}
public static TestListener createAdaptingListener(final RunNotifier notifier) {
return new OldTestClassAdaptingListener(notifier);
}
@Override
public Description getDescription() {
return makeDescription(fTest);
}
private Description makeDescription(Test test) {
if (test instanceof TestCase) {
TestCase tc= (TestCase) test;
return Description.createTestDescription(tc.getClass(), tc.getName());
} else if (test instanceof TestSuite) {
TestSuite ts= (TestSuite) test;
String name= ts.getName() == null ? "" : ts.getName();
Description description= Description.createSuiteDescription(name);
int n= ts.testCount();
for (int i= 0; i < n; i++)
description.addChild(makeDescription(ts.testAt(i)));
return description;
} else if (test instanceof JUnit4TestAdapter) {
JUnit4TestAdapter adapter= (JUnit4TestAdapter) test;
return adapter.getDescription();
} else if (test instanceof TestDecorator) {
TestDecorator decorator= (TestDecorator) test;
return makeDescription(decorator.getTest());
} else {
// This is the best we can do in this case
return Description.createSuiteDescription(test.getClass());
}
}
}
--- NEW FILE: JUnit4ClassRunner.java ---
package org.junit.internal.runners;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.manipulation.Filter;
import org.junit.runner.manipulation.Filterable;
import org.junit.runner.manipulation.NoTestsRemainException;
import org.junit.runner.manipulation.Sortable;
import org.junit.runner.manipulation.Sorter;
import org.junit.runner.notification.RunNotifier;
public class JUnit4ClassRunner extends Runner implements Filterable, Sortable {
private final List<Method> fTestMethods;
private TestClass fTestClass;
public JUnit4ClassRunner(Class<?> klass) throws InitializationError {
fTestClass= new TestClass(klass);
fTestMethods= fTestClass.getTestMethods();
validate();
}
protected void validate() throws InitializationError {
MethodValidator methodValidator= new MethodValidator(fTestClass);
methodValidator.validateMethodsForDefaultRunner();
methodValidator.assertValid();
}
@Override
public void run(final RunNotifier notifier) {
new ClassRoadie(notifier, fTestClass, getDescription(), new Runnable() {
public void run() {
runMethods(notifier);
}
}).runProtected();
}
protected void runMethods(final RunNotifier notifier) {
for (Method method : fTestMethods)
invokeTestMethod(method, notifier);
}
@Override
public Description getDescription() {
Description spec= Description.createSuiteDescription(getName());
List<Method> testMethods= fTestMethods;
for (Method method : testMethods)
spec.addChild(methodDescription(method));
return spec;
}
protected String getName() {
return getTestClass().getName();
}
protected Object createTest() throws Exception {
return getTestClass().getConstructor().newInstance();
}
protected void invokeTestMethod(Method method, RunNotifier notifier) {
Object test;
try {
test= createTest();
} catch (InvocationTargetException e) {
notifier.testAborted(methodDescription(method), e.getCause());
return;
} catch (Exception e) {
notifier.testAborted(methodDescription(method), e);
return;
}
createMethodRunner(test, method, notifier).run();
}
protected MethodRoadie createMethodRunner(Object test, Method method, RunNotifier notifier) {
return new MethodRoadie(test, method, notifier, methodDescription(method), fTestClass);
}
protected String testName(Method method) {
return method.getName();
}
protected Description methodDescription(Method method) {
return Description.createTestDescription(getTestClass().getJavaClass(), testName(method));
}
public void filter(Filter filter) throws NoTestsRemainException {
for (Iterator<Method> iter= fTestMethods.iterator(); iter.hasNext();) {
Method method= iter.next();
if (!filter.shouldRun(methodDescription(method)))
iter.remove();
}
if (fTestMethods.isEmpty())
throw new NoTestsRemainException();
}
public void sort(final Sorter sorter) {
Collections.sort(fTestMethods, new Comparator<Method>() {
public int compare(Method o1, Method o2) {
return sorter.compare(methodDescription(o1), methodDescription(o2));
}
});
}
protected TestClass getTestClass() {
return fTestClass;
}
}
--- NEW FILE: FailedBefore.java ---
package org.junit.internal.runners;
class FailedBefore extends Exception {
private static final long serialVersionUID= 1L;
}
--- NEW FILE: ClassRoadie.java ---
package org.junit.internal.runners;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import org.junit.runner.Description;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunNotifier;
public class ClassRoadie {
private RunNotifier fNotifier;
private TestClass fTestClass;
private Description fDescription;
private final Runnable fRunnable;
public ClassRoadie(RunNotifier notifier, TestClass testClass,
Description description, Runnable runnable) {
fNotifier= notifier;
fTestClass= testClass;
fDescription= description;
fRunnable= runnable;
}
protected void runUnprotected() {
fRunnable.run();
};
protected void addFailure(Throwable targetException) {
fNotifier.fireTestFailure(new Failure(fDescription, targetException));
}
public void runProtected() {
try {
runBefores();
runUnprotected();
} catch (FailedBefore e) {
} finally {
runAfters();
}
}
private void runBefores() throws FailedBefore {
try {
List<Method> befores= fTestClass.getBefores();
for (Method before : befores)
before.invoke(null);
} catch (InvocationTargetException e) {
addFailure(e.getTargetException());
throw new FailedBefore();
} catch (Throwable e) {
addFailure(e);
throw new FailedBefore();
}
}
private void runAfters() {
List<Method> afters= fTestClass.getAfters();
for (Method after : afters)
try {
after.invoke(null);
} catch (InvocationTargetException e) {
addFailure(e.getTargetException());
} catch (Throwable e) {
addFailure(e); // Untested, but seems impossible
}
}
}
Index: CompositeRunner.java
===================================================================
RCS file: /cvsroot/junit/junit/src/org/junit/internal/runners/CompositeRunner.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- CompositeRunner.java 6 Dec 2006 01:22:48 -0000 1.2
+++ CompositeRunner.java 20 Mar 2007 14:43:50 -0000 1.3
@@ -25,6 +25,10 @@
@Override
public void run(RunNotifier notifier) {
+ runChildren(notifier);
+ }
+
+ protected void runChildren(RunNotifier notifier) {
for (Runner each : fRunners)
each.run(notifier);
}
Index: MethodValidator.java
===================================================================
RCS file: /cvsroot/junit/junit/src/org/junit/internal/runners/MethodValidator.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- MethodValidator.java 21 Feb 2007 14:46:51 -0000 1.4
+++ MethodValidator.java 20 Mar 2007 14:43:50 -0000 1.5
@@ -13,21 +13,23 @@
import org.junit.Test;
public class MethodValidator {
- private final TestIntrospector fIntrospector;
private final List<Throwable> fErrors= new ArrayList<Throwable>();
- private final Class<?> fTestClass;
+ private TestClass fTestClass;
- public MethodValidator(Class<?> testClass) {
- fTestClass= testClass;
- fIntrospector= new TestIntrospector(testClass);
+ public MethodValidator(TestClass testClass) {
+ fTestClass = testClass;
}
public void validateInstanceMethods() {
validateTestMethods(After.class, false);
validateTestMethods(Before.class, false);
validateTestMethods(Test.class, false);
+
+ List<Method> methods= fTestClass.getAnnotatedMethods(Test.class);
+ if (methods.size() == 0)
+ fErrors.add(new Exception("No runnable methods"));
}
public void validateStaticMethods() {
@@ -57,7 +59,8 @@
private void validateTestMethods(Class<? extends Annotation> annotation,
boolean isStatic) {
- List<Method> methods= fIntrospector.getTestMethods(annotation);
+ List<Method> methods= fTestClass.getAnnotatedMethods(annotation);
+
for (Method each : methods) {
if (Modifier.isStatic(each.getModifiers()) != isStatic) {
String state= isStatic ? "should" : "should not";
--- TestIntrospector.java DELETED ---
--- TextListener.java DELETED ---
--- TestClassRunner.java DELETED ---
--- TestClassMethodsRunner.java DELETED ---
--- OldTestClassRunner.java DELETED ---
--- TestMethodRunner.java DELETED ---
--- BeforeAndAfterRunner.java DELETED ---
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV