Skip to content
Permalink
Browse files

Let TestNG be able to run also JUnit 4 tests

  • Loading branch information...
lukasj committed Dec 2, 2011
1 parent ad72beb commit 89f3b060dc074d4414e8e1dca409f74278278646
@@ -28,7 +28,7 @@ example.dir=${basedir}/examples
#
beanshell.jar=bsh-2.0b4.jar
guice2.jar=guice-2.0.jar
junit.jar=junit-3.8.1.jar
junit.jar=junit-4.10.jar
ant.jar=ant-1.6.5.jar
jcommander.jar=jcommander-1.13.jar
yaml.jar=snakeyaml-1.6.jar
@@ -39,7 +39,7 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<version>4.10</version>
</dependency>
<dependency>
<groupId>org.beanshell</groupId>
@@ -3,7 +3,7 @@

<dependencies>
<dependency org="ant" name="ant" rev="1.6.5" />
<dependency org="junit" name="junit" rev="3.8.1" />
<dependency org="junit" name="junit" rev="4.10" />
<dependency org="org.beanshell" name="bsh" rev="2.0b4" />
<dependency org="com.google.inject" name="guice" rev="2.0" />
<dependency org="org.yaml" name="snakeyaml" rev="1.6" />
@@ -45,7 +45,7 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<version>4.10</version>
</dependency>
<dependency>
<groupId>org.beanshell</groupId>
@@ -59,7 +59,7 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<version>4.10</version>
</dependency>
<dependency>
<groupId>org.beanshell</groupId>
@@ -96,7 +96,7 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<version>4.10</version>
</dependency>

<dependency>
@@ -187,7 +187,7 @@
bsh.*;version="[2.0.0,3.0.0)";resolution:=optional,
com.beust.jcommander.*;version="[1.7.0,3.0.0)";resolution:=optional,
com.google.inject.*;version="[1.2,1.3)";resolution:=optional,
junit.framework;version="[3.8.1, 4.0.0)";resolution:=optional,
junit.framework;version="[3.8.1, 5.0.0)";resolution:=optional,
org.apache.tools.ant.*;version="[1.6.5, 2.0.0)";resolution:=optional,
org.yaml.*;version="[1.6,2.0)";resolution:=optional,
!com.sun.*,
@@ -29,6 +29,7 @@
*/
public final class ClassHelper {
private static final String JUNIT_TESTRUNNER= "org.testng.junit.JUnitTestRunner";
private static final String JUNIT_4_TESTRUNNER = "org.testng.junit.JUnit4TestRunner";

/** The additional class loaders to find classes in. */
private static final List<ClassLoader> m_classLoaders = new Vector<ClassLoader>();
@@ -195,15 +196,23 @@ public static ConstructorOrMethod findDeclaredFactoryMethod(Class<?> cls,
* @return
*/
public static IJUnitTestRunner createTestRunner(TestRunner runner) {
try {
IJUnitTestRunner tr= (IJUnitTestRunner) ClassHelper.forName(JUNIT_TESTRUNNER).newInstance();
tr.setTestResultNotifier(runner);

return tr;
}
catch(Exception ex) {
throw new TestNGException("Cannot create JUnit runner " + JUNIT_TESTRUNNER, ex);
}
try {
//try to get runner for JUnit 4 first
IJUnitTestRunner tr = (IJUnitTestRunner) ClassHelper.forName(JUNIT_4_TESTRUNNER).newInstance();
tr.setTestResultNotifier(runner);
return tr;
} catch (Throwable t) {
try {
//fallback to JUnit 3
IJUnitTestRunner tr = (IJUnitTestRunner) ClassHelper.forName(JUNIT_TESTRUNNER).newInstance();
tr.setTestResultNotifier(runner);

return tr;
} catch (Exception ex) {
//there's no JUnit on the classpath
throw new TestNGException("Cannot create JUnit runner", ex);
}
}
}

private static Set<Method> extractMethods(Class<?> childClass, Class<?> clazz,
@@ -0,0 +1,177 @@
package org.testng.junit;

import java.util.*;
import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
import org.junit.runner.Request;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
import org.testng.ITestListener;
import org.testng.ITestNGMethod;
import org.testng.ITestResult;
import org.testng.TestNGException;
import org.testng.collections.Lists;
import org.testng.internal.ITestResultNotifier;
import org.testng.internal.InvokedMethod;
import org.testng.internal.TestResult;

/**
* A JUnit TestRunner that records/triggers all information/events necessary to
* TestNG.
*
* @author Lukas Jungmann
*/
public class JUnit4TestRunner implements IJUnitTestRunner {

private ITestResultNotifier m_parentRunner;
private List<ITestNGMethod> m_methods = Lists.newArrayList();
private List<ITestListener> m_listeners = Lists.newArrayList();

public JUnit4TestRunner() {
}

public JUnit4TestRunner(ITestResultNotifier tr) {
m_parentRunner = tr;
m_listeners = m_parentRunner.getTestListeners();
}

/**
* Needed from TestRunner in order to figure out what JUnit test methods
* were run.
*
* @return the list of all JUnit test methods run
*/
@Override
public List<ITestNGMethod> getTestMethods() {
return m_methods;
}

@Override
public void setTestResultNotifier(ITestResultNotifier notifier) {
m_parentRunner = notifier;
m_listeners = m_parentRunner.getTestListeners();
}

/**
* A
* <code>start</code> implementation that ignores the
* <code>TestResult</code>
*
* @param testClass the JUnit test class
*/
@Override
public void run(Class testClass) {
start(testClass);
}

/**
* Starts a test run. Analyzes the command line arguments and runs the given
* test suite.
*/
public Result start(Class testCase) {
try {
JUnitCore core = new JUnitCore();
core.addListener(new RL());
Request r = Request.aClass(testCase);
return core.run(r);
} catch (Throwable t) {
throw new TestNGException("Failure in JUnit mode for class " + testCase.getName(), t);
}
}

private class RL extends RunListener {

private Map<Description, ITestResult> runs = new WeakHashMap<Description, ITestResult>();
private List<Description> failures = new LinkedList<Description>();

@Override
public void testAssumptionFailure(Failure failure) {
super.testAssumptionFailure(failure);
ITestResult tr = runs.get(failure.getDescription());
tr.setStatus(TestResult.FAILURE);
tr.setEndMillis(Calendar.getInstance().getTimeInMillis());
tr.setThrowable(failure.getException());
for (ITestListener l : m_listeners) {
l.onTestFailure(tr);
}
}

@Override
public void testFailure(Failure failure) throws Exception {
super.testFailure(failure);
failures.add(failure.getDescription());
ITestResult tr = runs.get(failure.getDescription());
tr.setStatus(TestResult.FAILURE);
tr.setEndMillis(Calendar.getInstance().getTimeInMillis());
tr.setThrowable(failure.getException());
for (ITestListener l : m_listeners) {
l.onTestFailure(tr);
}
}

@Override
public void testFinished(Description description) throws Exception {
super.testFinished(description);
ITestResult tr = runs.get(description);
if (!failures.contains(description)) {
tr.setStatus(TestResult.SUCCESS);
tr.setEndMillis(Calendar.getInstance().getTimeInMillis());
for (ITestListener l : m_listeners) {
l.onTestSuccess(tr);
}
}
m_parentRunner.addInvokedMethod(new InvokedMethod(tr.getTestClass(), tr.getMethod(), new Object[0], true, false, tr.getStartMillis()));
m_methods.add(tr.getMethod());
}

@Override
public void testIgnored(Description description) throws Exception {
super.testIgnored(description);
ITestResult tr = createTestResult(description);
tr.setStatus(TestResult.SKIP);
tr.setEndMillis(tr.getStartMillis());
for (ITestListener l : m_listeners) {
l.onTestSkipped(tr);
}
m_parentRunner.addInvokedMethod(new InvokedMethod(tr.getTestClass(), tr.getMethod(), new Object[0], true, false, tr.getStartMillis()));
m_methods.add(tr.getMethod());
}

@Override
public void testRunFinished(Result result) throws Exception {
super.testRunFinished(result);
//TODO: ITestContext to be implemented by JUnitTestRunner
}

@Override
public void testRunStarted(Description description) throws Exception {
super.testRunStarted(description);
//TODO: ITestContext to be implemented by JUnitTestRunner
}

@Override
public void testStarted(Description description) throws Exception {
super.testStarted(description);
ITestResult tr = createTestResult(description);
runs.put(description, tr);
for (ITestListener l : m_listeners) {
l.onTestStart(tr);
}
}

private ITestResult createTestResult(Description test) {
JUnitUtils.JUnitTestClass tc = new JUnitUtils.JUnitTestClass(test);
JUnitUtils.JUnitTestMethod tm = new JUnitUtils.JUnitTestMethod(test, tc);

TestResult tr = new TestResult(tc,
test,
tm,
null,
Calendar.getInstance().getTimeInMillis(),
0);

return tr;
}
}
}
@@ -15,6 +15,7 @@

import junit.framework.Test;
import junit.framework.TestCase;
import org.junit.runner.Description;

/**
* Help methods for JUnit
@@ -60,6 +61,17 @@ public JUnitTestMethod(Test test, JUnitTestClass testClass) {
testClass.getTestMethodList().add(this);
}

public JUnitTestMethod(Description test, JUnitTestClass testClass) {
m_testClass= testClass;
m_instances= new Object[] {test};
m_instanceHashes= new long[] {test.hashCode()};
m_methodClass= test.getTestClass();

m_methodName = test.getMethodName();
m_signature = m_methodClass.getName() + "." + m_methodName + "()";
testClass.getTestMethodList().add(this);
}

private void init(Test test) {
if(TestCase.class.isAssignableFrom(test.getClass())) {
TestCase tc= (TestCase) test;
@@ -131,6 +143,15 @@ public Object getInstance() {
*/
@Override
public Method getMethod() {
if (m_method == null) {
try {
m_method = m_methodClass.getMethod(getMethodName());
} catch (NoSuchMethodException ex) {
// can be JUnit 3 - ignore
} catch (SecurityException ex) {
// can be JUnit 3 - ignore
}
}
return m_method;
}

@@ -558,6 +579,12 @@ public JUnitTestClass(Test test) {
m_instanceHashes= new long[] {test.hashCode()};
}

public JUnitTestClass(Description desc) {
m_realClass = desc.getTestClass();
m_instances = new Object[] {m_realClass};
m_instanceHashes = new long[] {m_realClass.hashCode()};
}

List<ITestNGMethod> getTestMethodList() {
return m_testMethods;
}
@@ -8,7 +8,7 @@ public static Test suite() {
TestSuite suite = new TestSuite("Suite2");
suite.addTestSuite(TestAc.class);
suite.addTestSuite(TestAd.class);
suite.addTestSuite(Suite3.class);
suite.addTest(Suite3.suite());
return suite;
}
}
@@ -22,7 +22,7 @@
</library>
</orderEntry>
<orderEntry type="library" name="Maven: ant:ant:1.6.5" level="project" />
<orderEntry type="library" name="Maven: junit:junit:3.8.1" level="project" />
<orderEntry type="library" name="Maven: junit:junit:4.10" level="project" />
<orderEntry type="library" name="Maven: org.beanshell:bsh:2.0b4" level="project" />
<orderEntry type="library" name="Maven: com.google.inject:guice:2.0" level="project" />
<orderEntry type="library" name="Maven: aopalliance:aopalliance:1.0" level="project" />

0 comments on commit 89f3b06

Please sign in to comment.
You can’t perform that action at this time.