Author: sebb
Date: Mon Sep 21 20:49:01 2009
New Revision: 817411
URL: http://svn.apache.org/viewvc?rev=817411&view=rev
Log:
Bugzilla 47803 - Support for JUnit 4.x tests defined by annotations
Merge code from JUnitAnnotatedSampler.java
Modified:
jakarta/jmeter/trunk/src/junit/org/apache/jmeter/protocol/java/sampler/JUnitSampler.java
Modified:
jakarta/jmeter/trunk/src/junit/org/apache/jmeter/protocol/java/sampler/JUnitSampler.java
URL:
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/junit/org/apache/jmeter/protocol/java/sampler/JUnitSampler.java?rev=817411&r1=817410&r2=817411&view=diff
==============================================================================
---
jakarta/jmeter/trunk/src/junit/org/apache/jmeter/protocol/java/sampler/JUnitSampler.java
(original)
+++
jakarta/jmeter/trunk/src/junit/org/apache/jmeter/protocol/java/sampler/JUnitSampler.java
Mon Sep 21 20:49:01 2009
@@ -17,6 +17,7 @@
*/
package org.apache.jmeter.protocol.java.sampler;
+import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -35,6 +36,10 @@
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.Test.None;
/**
*
@@ -74,22 +79,32 @@
private transient Method TDOWN_METHOD = null;
private boolean checkStartUpTearDown = false;
+ // The TestCase to run
private transient TestCase TEST_INSTANCE = null;
+ // The test object; same as TEST_INSTANCE for JUnit3 tests
+ // but different for JUnit4 tests
+ private transient Object TEST_OBJECT = null;
public JUnitSampler(){
}
/**
* Method tries to get the setUp and tearDown method for the class
- * @param tc
+ * @param testObject
*/
- private void initMethodObjects(TestCase tc){
+ private void initMethodObjects(Object testObject){
if (!this.checkStartUpTearDown && !getDoNotSetUpTearDown()) {
if (SETUP_METHOD == null) {
- SETUP_METHOD = getMethod(tc, SETUP);
+ SETUP_METHOD = getJunit4() ?
+ getMethodWithAnnotation(testObject, Before.class)
+ :
+ getMethod(testObject, SETUP);
}
if (TDOWN_METHOD == null) {
- TDOWN_METHOD = getMethod(tc, TEARDOWN);
+ TDOWN_METHOD = getJunit4() ?
+ getMethodWithAnnotation(testObject, After.class)
+ :
+ getMethod(testObject, TEARDOWN);
}
this.checkStartUpTearDown = true;
}
@@ -348,19 +363,40 @@
// check to see if the test class is null. if it is, we create
// a new instance. this should only happen at the start of a
// test run
- if (this.TEST_INSTANCE == null) {
- this.TEST_INSTANCE = (TestCase)getClassInstance(className,rlabel);
+ if (this.TEST_OBJECT == null) {
+ this.TEST_OBJECT = getClassInstance(className,rlabel);
}
- if (this.TEST_INSTANCE != null){
- initMethodObjects(this.TEST_INSTANCE);
+ if (this.TEST_OBJECT != null){
+ initMethodObjects(this.TEST_OBJECT);
+ final Method m = getMethod(this.TEST_OBJECT,methodName);
// create a new TestResult
TestResult tr = new TestResult();
+ long timeout = 0L;
+ Class<? extends Throwable> expectedException = null;
+ if (getJunit4()){
+ try {
+ TEST_INSTANCE = new AnnotatedTestCase();
+ } catch (SecurityException e) {
+ log.error(e.getLocalizedMessage(),e);
+ return sresult;
+ } catch( NoSuchMethodException e) {
+ log.error(e.getLocalizedMessage(),e);
+ return sresult;
+ }
+ Test annotation = m.getAnnotation(Test.class);
+ if(null != annotation) {
+ expectedException = annotation.expected();
+ timeout = annotation.timeout();
+ }
+ } else {
+ this.TEST_INSTANCE = (TestCase) this.TEST_OBJECT;
+ }
this.TEST_INSTANCE.setName(methodName);
try {
if (!getDoNotSetUpTearDown() && SETUP_METHOD != null){
try {
- SETUP_METHOD.invoke(this.TEST_INSTANCE,new Object[0]);
+ SETUP_METHOD.invoke(this.TEST_OBJECT,new Object[0]);
} catch (InvocationTargetException e) {
tr.addFailure(this.TEST_INSTANCE,
new AssertionFailedError(e.getMessage()));
@@ -372,7 +408,6 @@
new AssertionFailedError(e.getMessage()));
}
}
- final Method m = getMethod(this.TEST_INSTANCE,methodName);
final TestCase theClazz = this.TEST_INSTANCE;
tr.startTest(this.TEST_INSTANCE);
sresult.sampleStart();
@@ -380,26 +415,64 @@
// call setUp and tearDown. Doing that will result in calling
// the setUp and tearDown method twice and the elapsed time
// will include setup and teardown.
- Protectable p = new Protectable() {
- public void protect() throws Throwable {
- m.invoke(theClazz,new Object[0]);
+ Throwable thrown = null;
+ if (getJunit4()){
+ try {
+ theClazz.runBare();
+ } catch(Throwable t) {
+ thrown = t;
}
- };
- tr.runProtected(theClazz, p);
+ } else {
+ Protectable p = new Protectable() {
+ public void protect() throws Throwable {
+ m.invoke(theClazz,new Object[0]);
+ }
+ };
+ tr.runProtected(theClazz, p);
+ }
tr.endTest(this.TEST_INSTANCE);
sresult.sampleEnd();
-
+ if (getJunit4()){
+ if(null == thrown) {
+ if (expectedException != None.class) {
+ tr.addFailure(
+ this.TEST_INSTANCE,
+ new AssertionFailedError(
+ "No error was generated for a test case
which specifies an error."));
+ throw new Exception(
+ "Unexpected lack of exception from the test
case: "
+ + getMethod());
+ }
+ else {
+ //this is a pass condition
+ }
+ }
+ else {
+ //unravel 1x. InvocationTargetException wraps the
real exception.
+ thrown = thrown.getCause();
+ if
(expectedException.isAssignableFrom(thrown.getClass()))
+ // &&
thrown.getClass().isAssignableFrom(expectedException))
+ {
+ //The test actually passed
+ log.debug("Test passed for " + getMethod());
+ } else {
+ tr.addFailure(this.TEST_INSTANCE, new
AssertionFailedError("The wrong exception was thrown from the test case"));
+ throw new Exception("The wrong exception was
thrown from the test case");
+ }
+ }
+ if( timeout > 0L && timeout < sresult.getTime()) {
+ tr.addFailure(this.TEST_INSTANCE, new
AssertionFailedError("Test took longer than speficied timeout."));
+ }
+ }
if (!getDoNotSetUpTearDown() && TDOWN_METHOD != null){
- TDOWN_METHOD.invoke(TEST_INSTANCE,new Object[0]);
+ TDOWN_METHOD.invoke(TEST_OBJECT,new Object[0]);
}
} catch (InvocationTargetException e) {
- // log.warn(e.getMessage());
sresult.setResponseCode(getErrorCode());
sresult.setResponseMessage(getError());
sresult.setResponseData(e.getMessage().getBytes());
sresult.setSuccessful(false);
} catch (IllegalAccessException e) {
- // log.warn(e.getMessage());
sresult.setResponseCode(getErrorCode());
sresult.setResponseMessage(getError());
sresult.setResponseData(e.getMessage().getBytes());
@@ -551,4 +624,27 @@
}
return null;
}
+
+ private Method getMethodWithAnnotation(Object clazz, Class<? extends
Annotation> annotation) {
+ if(null != clazz && null != annotation) {
+ for(Method m : clazz.getClass().getMethods()) {
+ if(m.isAnnotationPresent(annotation)) {
+ return m;
+ }
+ }
+ }
+ return null;
+ }
+
+ private class AnnotatedTestCase extends TestCase {
+ private final Method m;
+ public AnnotatedTestCase() throws SecurityException,
NoSuchMethodException {
+ m = TEST_OBJECT.getClass().getMethod(getMethod(), (Class[])null);
+ }
+
+ @Override
+ protected void runTest() throws Throwable {
+ m.invoke(TEST_OBJECT, (Object[])null);
+ }
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]