Skip to content
Permalink
Browse files

initial version of mixed mode for TestNG:

-added '-mixed' cmd line switch and mode="TESTNG|JUNIT|MIXED" ant task attribute

-when this mode is selected and some version of JUnit is found on the classpath then TestNG tries to automatically recognize the type of test and run it using appropriate test runner (testng for testng, junitcore for junit4/3 - if junit4 is found or junit 3 runner - if only junit3 is found)

-improved test results reporting for invoked JUnit tests
  • Loading branch information...
lukasj committed Feb 1, 2012
1 parent 1522307 commit 1876355ae9a570f93b2222d9d03599712d732ca1
Showing with 732 additions and 784 deletions.
  1. +3 −3 build-tests.xml
  2. +5 −0 src/main/java/org/testng/CommandLineArgs.java
  3. +34 −1 src/main/java/org/testng/TestNG.java
  4. +13 −3 src/main/java/org/testng/TestNGAntTask.java
  5. +12 −2 src/main/java/org/testng/TestRunner.java
  6. +6 −1 src/main/java/org/testng/internal/ClassInfoMap.java
  7. +6 −3 src/main/java/org/testng/junit/IJUnitTestRunner.java
  8. +14 −0 src/main/java/org/testng/junit/JUnit3TestClass.java
  9. +29 −0 src/main/java/org/testng/junit/JUnit3TestMethod.java
  10. +41 −0 src/main/java/org/testng/junit/JUnit3TestRecognizer.java
  11. +14 −0 src/main/java/org/testng/junit/JUnit4TestClass.java
  12. +33 −0 src/main/java/org/testng/junit/JUnit4TestMethod.java
  13. +27 −0 src/main/java/org/testng/junit/JUnit4TestRecognizer.java
  14. +46 −15 src/main/java/org/testng/junit/JUnit4TestRunner.java
  15. +193 −0 src/main/java/org/testng/junit/JUnitTestClass.java
  16. +53 −0 src/main/java/org/testng/junit/JUnitTestFinder.java
  17. +30 −0 src/main/java/org/testng/junit/JUnitTestMethod.java
  18. +10 −0 src/main/java/org/testng/junit/JUnitTestRecognizer.java
  19. +44 −9 src/main/java/org/testng/junit/JUnitTestRunner.java
  20. +0 −747 src/main/java/org/testng/junit/JUnitUtils.java
  21. +4 −0 src/main/java/org/testng/xml/XmlSuite.java
  22. +22 −0 src/test/java/test/mixed/JUnit3Test1.java
  23. +20 −0 src/test/java/test/mixed/JUnit4Test1.java
  24. +45 −0 src/test/java/test/mixed/MixedTest.java
  25. +21 −0 src/test/java/test/mixed/TestNGTest1.java
  26. +7 −0 src/test/resources/testng.xml
@@ -27,7 +27,7 @@ JUNIT.REPORT.DIR =${junit.report.dir}
TESTNG.REPORT.DIR=${testng.report.dir}
</echo>
</target>

<target name="compile" depends="prepare">
<echo message=" -- Compiling tests --"/>

@@ -38,15 +38,15 @@ TESTNG.REPORT.DIR=${testng.report.dir}
srcdir="${test.dir}"
destdir="${test.build.dir}"
/>

</target>

<target name="prepare">
<tstamp/>
<mkdir dir="${test.build.dir}"/>
<mkdir dir="${junit.report.dir}"/>
<mkdir dir="${testng.report.dir}"/>

<taskdef name="testng"
classname="org.testng.TestNGAntTask"
classpath="${build.dir}"/>
@@ -35,6 +35,11 @@
@Parameter(names = JUNIT, description ="JUnit mode")
public Boolean junit = Boolean.FALSE;

public static final String MIXED = "-mixed";
@Parameter(names = MIXED, description ="Mixed mode - autodetect the type of current test" +
" and run it with appropriate runner")
public Boolean mixed = Boolean.FALSE;

public static final String LISTENER = "-listener";
@Parameter(names = LISTENER, description = "List of .class files or list of class names" +
" implementing ITestListener or ISuiteListener")
@@ -64,6 +64,7 @@
import java.util.concurrent.TimeUnit;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.testng.junit.JUnitTestFinder;

/**
* This class is the main entry point for running tests in the TestNG framework.
@@ -129,6 +130,7 @@
private String[] m_excludedGroups;

private Boolean m_isJUnit = XmlSuite.DEFAULT_JUNIT;
private Boolean m_isMixed = XmlSuite.DEFAULT_MIXED;
protected boolean m_useDefaultListeners = true;

private ITestRunnerFactory m_testRunnerFactory;
@@ -497,7 +499,13 @@ public void setTestClasses(Class[] classes) {
//
// Add the method tags
//
List<XmlClass> xmlClasses = result.get(0).getTests().get(0).getXmlClasses();
List<XmlClass> xmlClasses = Lists.newArrayList();
for (XmlSuite s : result) {
for (XmlTest t : s.getTests()) {
xmlClasses.addAll(t.getClasses());
}
}

for (XmlClass xc : xmlClasses) {
for (String m : commandLineMethods) {
String[] split = splitMethod(m);
@@ -527,9 +535,15 @@ public void setTestClasses(Class[] classes) {
ITestAnnotation test = (ITestAnnotation) finder.findAnnotation(c, ITestAnnotation.class);
String suiteName = getDefaultSuiteName();
String testName = getDefaultTestName();
boolean isJUnit = false;
if (test != null) {
suiteName = defaultIfStringEmpty(test.getSuiteName(), suiteName);
testName = defaultIfStringEmpty(test.getTestName(), testName);
} else {
if (m_isMixed && JUnitTestFinder.isJUnitTest(c)) {
isJUnit = true;
testName = c.getName();
}
}
XmlSuite xmlSuite = suites.get(suiteName);
if (xmlSuite == null) {
@@ -552,6 +566,7 @@ public void setTestClasses(Class[] classes) {
if (xmlTest == null) {
xmlTest = new XmlTest(xmlSuite);
xmlTest.setName(testName);
xmlTest.setJUnit(isJUnit);
}

xmlTest.getXmlClasses().add(xmlClasses[i]);
@@ -1343,6 +1358,7 @@ protected void configure(CommandLineArgs cla) {
setTestJar(cla.testJar);
setXmlPathInJar(cla.xmlPathInJar);
setJUnit(cla.junit);
setMixed(cla.mixed);
setMaster(cla.master);
setSlave(cla.slave);
setSkipFailedInvocationCounts(cla.skipFailedInvocationCounts);
@@ -1479,6 +1495,7 @@ public void configure(Map cmdLineArgs) {
result.testJar = (String) cmdLineArgs.get(CommandLineArgs.TEST_JAR);
result.xmlPathInJar = (String) cmdLineArgs.get(CommandLineArgs.XML_PATH_IN_JAR);
result.junit = (Boolean) cmdLineArgs.get(CommandLineArgs.JUNIT);
result.mixed = (Boolean) cmdLineArgs.get(CommandLineArgs.MIXED);
result.master = (String) cmdLineArgs.get(CommandLineArgs.MASTER);
result.slave = (String) cmdLineArgs.get(CommandLineArgs.SLAVE);
result.skipFailedInvocationCounts = (Boolean) cmdLineArgs.get(
@@ -1590,6 +1607,15 @@ public void setJUnit(Boolean isJUnit) {
m_isJUnit = isJUnit;
}

/**
* Specify if this run should be made in mixed mode
*
* @param isJUnit
*/
public void setMixed(Boolean isMixed) {
m_isMixed = isMixed;
}

/**
* @deprecated The TestNG version is now established at load time. This
* method is not required anymore and is now a no-op.
@@ -1639,6 +1665,13 @@ protected static void validateCommandLineParameters(CommandLineArgs args) {
throw new ParameterException(CommandLineArgs.SLAVE + " can't be combined with "
+ CommandLineArgs.MASTER);
}

Boolean junit = args.junit;
Boolean mixed = args.mixed;
if (junit && mixed) {
throw new ParameterException(CommandLineArgs.MIXED + " can't be combined with "
+ CommandLineArgs.JUNIT);
}
}

/**
@@ -113,7 +113,6 @@
protected File m_testjar;
protected File m_workingDir;
private Integer m_timeout;
protected Boolean m_isJUnit;
private List<String> m_listeners= Lists.newArrayList();
private List<String> m_methodselectors= Lists.newArrayList();
private String m_objectFactory;
@@ -151,7 +150,12 @@
private String m_testName="Ant test";
private Boolean m_skipFailedInvocationCounts;
private String m_methods;
private Mode mode = Mode.TESTNG;

public enum Mode {
TESTNG, JUNIT, MIXED;
}

/**
* The list of report listeners added via &lt;reporter&gt; sub-element of the Ant task
*/
@@ -367,7 +371,12 @@ public void setTestName(String s) {

// TestNG settings
public void setJUnit(boolean value) {
m_isJUnit= Boolean.valueOf(value);
mode = value ? Mode.JUNIT : Mode.TESTNG;
}

// TestNG settings
public void setMode(Mode mode) {
this.mode = mode;
}

/**
@@ -528,7 +537,8 @@ public void execute() throws BuildException {

private List<String> createArguments() {
List<String> argv= Lists.newArrayList();
addBooleanIfTrue(argv, CommandLineArgs.JUNIT, m_isJUnit);
addBooleanIfTrue(argv, CommandLineArgs.JUNIT, mode == Mode.JUNIT);
addBooleanIfTrue(argv, CommandLineArgs.MIXED, mode == Mode.MIXED);
addBooleanIfTrue(argv, CommandLineArgs.SKIP_FAILED_INVOCATION_COUNTS, m_skipFailedInvocationCounts);
addIntegerIfNotNull(argv, CommandLineArgs.LOG, m_verbose);
addDefaultListeners(argv);
@@ -52,6 +52,7 @@
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import org.testng.xml.*;

/**
* This class takes care of running one Test.
@@ -80,6 +81,8 @@
transient private IConfigurationListener m_confListener= new ConfigurationListener();
transient private boolean m_skipFailedInvocationCounts;

transient private List<IInvokedMethodListener> m_invokedMethodListeners = Lists.newArrayList();

/**
* All the test methods we found, associated with their respective classes.
* Note that these test methods might belong to different classes.
@@ -188,6 +191,7 @@ private void init(IConfiguration configuration,
}

m_annotationFinder= annotationFinder;
m_invokedMethodListeners = invokedMethodListeners;
m_invoker = new Invoker(m_configuration, this, this, m_suite.getSuiteState(),
m_skipFailedInvocationCounts, invokedMethodListeners);

@@ -644,7 +648,7 @@ private void beforeRun() {
}

private void privateRunJUnit(XmlTest xmlTest) {
ClassInfoMap cim = new ClassInfoMap(m_testClassesFromXml);
final ClassInfoMap cim = new ClassInfoMap(m_testClassesFromXml, false);
final Set<Class<?>> classes = cim.getClasses();
final List<ITestNGMethod> runMethods = Lists.newArrayList();
List<IWorker<ITestNGMethod>> workers = Lists.newArrayList();
@@ -667,9 +671,15 @@ public long getTimeOut() {
@Override
public void run() {
for(Class<?> tc: classes) {
List<XmlInclude> includedMethods = cim.getXmlClass(tc).getIncludedMethods();
List<String> methods = Lists.newArrayList();
for (XmlInclude inc: includedMethods) {
methods.add(inc.getName());
}
IJUnitTestRunner tr= ClassHelper.createTestRunner(TestRunner.this);
tr.setInvokedMethodListeners(m_invokedMethodListeners);
try {
tr.run(tc);
tr.run(tc, methods.toArray(new String[methods.size()]));
}
catch(Exception ex) {
ex.printStackTrace();
@@ -9,11 +9,17 @@

public class ClassInfoMap {
private Map<Class<?>, XmlClass> m_map = Maps.newHashMap();
private boolean includeNestedClasses;

public ClassInfoMap() {
}

public ClassInfoMap(List<XmlClass> classes) {
this(classes, true);
}

public ClassInfoMap(List<XmlClass> classes, boolean includeNested) {
includeNestedClasses = includeNested;
for (XmlClass xmlClass : classes) {
try {
Class c = xmlClass.getSupportClass();
@@ -29,7 +35,6 @@ public ClassInfoMap(List<XmlClass> classes) {
}

private void registerClass(Class cl, XmlClass xmlClass) {
boolean includeNestedClasses = true;
m_map.put(cl, xmlClass);
if (includeNestedClasses) {
for (Class c : cl.getClasses()) {
@@ -1,20 +1,23 @@
package org.testng.junit;

import java.util.List;
import org.testng.IInvokedMethodListener;
import org.testng.ITestNGMethod;
import org.testng.internal.ITestResultNotifier;

import java.util.List;


/**
* An abstraction interface over JUnit test runners.
*
* @author <a href='mailto:the_mindstorm@evolva.ro'>Alexandru Popescu</a>
*/
public interface IJUnitTestRunner {

void setInvokedMethodListeners(List<IInvokedMethodListener> listener);

void setTestResultNotifier(ITestResultNotifier notifier);

void run(Class junitTestClass);
void run(Class junitTestClass, String... methods);

List<ITestNGMethod> getTestMethods();

@@ -0,0 +1,14 @@
package org.testng.junit;

import junit.framework.Test;

/**
*
* @author lukas
*/
public class JUnit3TestClass extends JUnitTestClass {

public JUnit3TestClass(Test test) {
super(test.getClass());
}
}
@@ -0,0 +1,29 @@
package org.testng.junit;

import java.lang.reflect.Method;
import junit.framework.Test;
import org.testng.internal.Utils;

/**
*
* @author lukas
*/
public class JUnit3TestMethod extends JUnitTestMethod {

public JUnit3TestMethod(JUnitTestClass owner, Test test) {
super(owner, getMethod(test), test);
}

private static Method getMethod(Test t) {
String name = null;
try {
Method nameMethod = t.getClass().getMethod("getName");
name = (String) nameMethod.invoke(t);
return t.getClass().getMethod(name);
} catch (Throwable th) {
Utils.log("JUnit4TestMethod", 2,
"Method '" + name + "' not found in class '" + t + "': " + th.getMessage());
return null;
}
}
}
@@ -0,0 +1,41 @@
package org.testng.junit;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import junit.framework.Test;

/**
*
* @author lukas
*/
public class JUnit3TestRecognizer implements JUnitTestRecognizer {

public JUnit3TestRecognizer() {
}

public boolean isTest(Class c) {
//class implementing junit.framework.Test with at least one test* method
if (Test.class.isAssignableFrom(c)) {
boolean haveTest = false;
for (Method m : c.getMethods()) {
if (m.getName().startsWith("test")) {
haveTest = true;
break;
}
}
if (haveTest) {
return true;
}
}
try {
//or a class with public static Test suite() method
Method m = c.getDeclaredMethod("suite");
if (Modifier.isPublic(m.getModifiers()) && Modifier.isStatic(m.getModifiers())) {
return m.getReturnType().isAssignableFrom(Test.class);
}
} catch (Throwable t) {
return false;
}
return false;
}
}
@@ -0,0 +1,14 @@
package org.testng.junit;

import org.junit.runner.Description;

/**
*
* @author lukas
*/
public class JUnit4TestClass extends JUnitTestClass {

public JUnit4TestClass(Description test) {
super(test.getTestClass());
}
}

0 comments on commit 1876355

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