CVS: junit/src/org/junit/internal/runners TestMethod.java, NONE, 1.1 TestClassMethodsRunner.java, 1.1, 1.2 TestIntrospector.java, 1.2, 1.3

David Saff <[email protected]>
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-serv23274/src/org/junit/internal/runners

Modified Files:
	TestClassMethodsRunner.java TestIntrospector.java 
Added Files:
	TestMethod.java 
Log Message:
Another potential enhancement.  RunMethodWith allows individual test methods to be run with different runners.

--- NEW FILE: TestMethod.java ---
package org.junit.internal.runners;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;

import org.junit.runner.Description;
import org.junit.runners.MethodRunner;
import org.junit.runners.RunMethodWith;

public class TestMethod {
	private final Object fTest;

	private final Method fJavaMethod;

	private final Description fDescription;

	public TestMethod(Object test, Method javaMethod, Description description) {
		fTest= test;
		fJavaMethod= javaMethod;
		fDescription= description;
	}

	public Description getDescription() {
		return fDescription;
	}

	public Object getTest() {
		return fTest;
	}

	public Method getJavaMethod() {
		return fJavaMethod;
	}

	MethodRunner findCustomRunner(TestClassMethodsRunner testClassMethodsRunner)
			throws Exception {
		Method method= getJavaMethod();
		AnnotatedElement method2= method;
		MethodRunner methodRunner= createCustomRunner(method2);
		if (methodRunner != null)
			return methodRunner;

		for (Annotation a : method2.getAnnotations()) {
			AnnotatedElement annotationType= a.annotationType();
			MethodRunner arunner= createCustomRunner(annotationType);
			if (arunner != null)
				return arunner;
		}

		return null;
	}

	private MethodRunner createCustomRunner(AnnotatedElement annotationType)
			throws Exception {
		RunMethodWith runMethodWith= annotationType
				.getAnnotation(RunMethodWith.class);
		if (runMethodWith != null)
			return runMethodWith.value().newInstance();
		return null;
	}

}

Index: TestClassMethodsRunner.java
===================================================================
RCS file: /cvsroot/junit/junit/src/org/junit/internal/runners/TestClassMethodsRunner.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- TestClassMethodsRunner.java	21 Nov 2006 18:53:34 -0000	1.1
+++ TestClassMethodsRunner.java	27 Dec 2006 22:27:22 -0000	1.2
@@ -17,28 +17,33 @@
 import org.junit.runner.manipulation.Sorter;
 import org.junit.runner.notification.Failure;
 import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.MethodRunner;
 
-public class TestClassMethodsRunner extends Runner implements Filterable, Sortable {
+public class TestClassMethodsRunner extends Runner implements Filterable,
+		Sortable {
 	private final List<Method> fTestMethods;
+
 	private final Class<?> fTestClass;
 
-	// This assumes that some containing runner will perform validation of the test methods	
+	// This assumes that some containing runner will perform validation of the
+	// test methods
 	public TestClassMethodsRunner(Class<?> klass) {
 		fTestClass= klass;
-		fTestMethods= new TestIntrospector(getTestClass()).getTestMethods(Test.class);
+		fTestMethods= new TestIntrospector(getTestClass())
+				.getTestMethods(Test.class);
 	}
-	
+
 	@Override
 	public void run(RunNotifier notifier) {
 		if (fTestMethods.isEmpty())
-			testAborted(notifier, getDescription(), new Exception("No runnable methods"));
+			testAborted(notifier, getDescription(), new Exception(
+					"No runnable methods"));
 		for (Method method : fTestMethods)
 			invokeTestMethod(method, notifier);
 	}
 
-	private void testAborted(RunNotifier notifier, Description description, Throwable cause) {
-		// TODO: duped!
-		// TODO: envious
+	private void testAborted(RunNotifier notifier, Description description,
+			Throwable cause) {
 		notifier.fireTestStarted(description);
 		notifier.fireTestFailure(new Failure(description, cause));
 		notifier.fireTestFinished(description);
@@ -49,14 +54,14 @@
 		Description spec= Description.createSuiteDescription(getName());
 		List<Method> testMethods= fTestMethods;
 		for (Method method : testMethods)
-				spec.addChild(methodDescription(method));
+			spec.addChild(methodDescription(method));
 		return spec;
 	}
 
 	protected String getName() {
 		return getTestClass().getName();
 	}
-	
+
 	protected Object createTest() throws Exception {
 		return getTestClass().getConstructor().newInstance();
 	}
@@ -66,17 +71,38 @@
 		try {
 			test= createTest();
 		} catch (InvocationTargetException e) {
-			testAborted(notifier, methodDescription(method), e.getCause());
-			return;			
-		} catch (Exception e) {
-			testAborted(notifier, methodDescription(method), e);
+			testAborted(notifier, method, e.getCause());
+			return;
+		} catch (Throwable e) {
+			testAborted(notifier, method, e);
 			return;
 		}
-		createMethodRunner(test, method, notifier).run();
+
+		TestMethod testMethod= new TestMethod(test, method,
+				methodDescription(method));
+		try {
+			MethodRunner runner= testMethod.findCustomRunner(this);
+			if (runner == null)
+				createMethodRunner(test, method, notifier).run();
+			else {
+				runner.run(testMethod, notifier);
+			}
+		} catch (Exception e) {
+			Throwable exception= new RuntimeException(
+					"Exception creating custom method runner", e);
+			testAborted(notifier, method, exception);
+		}
 	}
 
-	protected TestMethodRunner createMethodRunner(Object test, Method method, RunNotifier notifier) {
-		return new TestMethodRunner(test, method, notifier, methodDescription(method));
+	private void testAborted(RunNotifier notifier, Method method,
+			Throwable cause) {
+		testAborted(notifier, methodDescription(method), cause);
+	}
+
+	protected TestMethodRunner createMethodRunner(Object test, Method method,
+			RunNotifier notifier) {
+		return new TestMethodRunner(test, method, notifier,
+				methodDescription(method));
 	}
 
 	protected String testName(Method method) {
@@ -84,7 +110,8 @@
 	}
 
 	protected Description methodDescription(Method method) {
-		return Description.createTestDescription(getTestClass(), testName(method));
+		return Description.createTestDescription(getTestClass(),
+				testName(method));
 	}
 
 	public void filter(Filter filter) throws NoTestsRemainException {
@@ -100,7 +127,8 @@
 	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));
+				return sorter.compare(methodDescription(o1),
+						methodDescription(o2));
 			}
 		});
 	}

Index: TestIntrospector.java
===================================================================
RCS file: /cvsroot/junit/junit/src/org/junit/internal/runners/TestIntrospector.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- TestIntrospector.java	27 Dec 2006 17:45:54 -0000	1.2
+++ TestIntrospector.java	27 Dec 2006 22:27:22 -0000	1.3
@@ -11,6 +11,7 @@
 import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.Test.None;
+import org.junit.runners.Replaces;
 
 public class TestIntrospector {
 	private static class MethodCollector {
@@ -24,21 +25,36 @@
 
 		public MethodCollector addMethods(Class<?> testClass) {
 			for (Method eachMethod : testClass.getDeclaredMethods()) {
-				Annotation annotation= eachMethod
-						.getAnnotation(annotationClass);
-				if (annotation != null && !isShadowed(eachMethod))
+				if (hasAnnotation(eachMethod) && !isShadowed(eachMethod))
 					methods.add(eachMethod);
 			}
-			
-			addSuperclasses(testClass);			
+
+			addSuperclasses(testClass);
 			addMixins(testClass);
 			return this;
 		}
 
+		private boolean hasAnnotation(Method method) {
+			return method.getAnnotation(annotationClass) != null
+					|| hasReplacementAnnotation(method);
+		}
+
+		private boolean hasReplacementAnnotation(Method method) {
+			Annotation[] annotations= method.getAnnotations();
+			for (Annotation annotation : annotations) {
+				Replaces replaces= annotation.annotationType().getAnnotation(
+						Replaces.class);
+				if (replaces != null
+						&& replaces.value().equals(annotationClass))
+					return true;
+			}
+			return false;
+		}
+
 		private void addMixins(Class<?> testClass) {
 			MixIn mixins= testClass.getAnnotation(MixIn.class);
 			if (mixins != null)
-				for (Class<?> type : mixins.value())					
+				for (Class<?> type : mixins.value())
 					addMethods(type);
 		}
 
@@ -90,8 +106,8 @@
 		return results;
 	}
 
-	public boolean isIgnored(Method eachMethod) {
-		return eachMethod.getAnnotation(Ignore.class) != null;
+	public boolean isIgnored(Method method) {
+		return method.getAnnotation(Ignore.class) != null;
 	}
 
 	private boolean runsTopToBottom(Class<? extends Annotation> annotation) {
@@ -101,12 +117,15 @@
 
 	long getTimeout(Method method) {
 		Test annotation= method.getAnnotation(Test.class);
-		long timeout= annotation.timeout();
-		return timeout;
+		if (annotation == null)
+			return 0;
+		return annotation.timeout();
 	}
 
 	Class<? extends Throwable> expectedException(Method method) {
 		Test annotation= method.getAnnotation(Test.class);
+		if (annotation == null)
+			return null;
 		if (annotation.expected() == None.class)
 			return null;
 		else


-------------------------------------------------------------------------
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.