org.testng.internal.TestMethodWorker Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of testng Show documentation
Show all versions of testng Show documentation
A testing framework for the JVM
package org.testng.internal;
import org.testng.ClassMethodMap;
import org.testng.IClassListener;
import org.testng.IMethodInstance;
import org.testng.ITestClass;
import org.testng.ITestContext;
import org.testng.ITestNGMethod;
import org.testng.ITestResult;
import org.testng.collections.Lists;
import org.testng.internal.thread.graph.IWorker;
import org.testng.xml.XmlSuite;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* FIXME: reduce contention when this class is used through parallel invocation due to
* invocationCount and threadPoolSize by not invoking the @BeforeClass and @AfterClass
* which are already invoked on the original method.
*
* This class implements Runnable and will invoke the ITestMethod passed in its
* constructor on its run() method.
*/
public class TestMethodWorker implements IWorker {
// Map of the test methods and their associated instances
// It has to be a set because the same method can be passed several times
// and associated to a different instance
private List m_methodInstances;
private final IInvoker m_invoker;
private final Map m_parameters;
private final XmlSuite m_suite;
private List m_testResults = Lists.newArrayList();
private final ConfigurationGroupMethods m_groupMethods;
private final ClassMethodMap m_classMethodMap;
private final ITestContext m_testContext;
private final List m_listeners;
public TestMethodWorker(IInvoker invoker,
List testMethods,
XmlSuite suite,
Map parameters,
ConfigurationGroupMethods groupMethods,
ClassMethodMap classMethodMap,
ITestContext testContext,
List listeners)
{
m_invoker = invoker;
m_methodInstances = testMethods;
m_suite = suite;
m_parameters = parameters;
m_groupMethods = groupMethods;
m_classMethodMap = classMethodMap;
m_testContext = testContext;
m_listeners = listeners;
}
/**
* Retrieves the maximum specified timeout of all ITestNGMethods to
* be run.
*
* @return the max timeout or 0 if no timeout was specified
*/
@Override
public long getTimeOut() {
long result = 0;
for (IMethodInstance mi : m_methodInstances) {
ITestNGMethod tm = mi.getMethod();
if (tm.getTimeOut() > result) {
result = tm.getTimeOut();
}
}
return result;
}
@Override
public String toString() {
StringBuilder result = new StringBuilder("[Worker thread:" + Thread.currentThread().getId()
+ " priority:" + getPriority() + " ");
for (IMethodInstance m : m_methodInstances) {
result.append(m.getMethod()).append(" ");
}
result.append("]");
return result.toString();
}
/**
* Run all the ITestNGMethods passed in through the constructor.
*
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
for (IMethodInstance testMthdInst : m_methodInstances) {
ITestNGMethod testMethod = testMthdInst.getMethod();
ITestClass testClass = testMethod.getTestClass();
invokeBeforeClassMethods(testClass, testMthdInst);
// Invoke test method
try {
invokeTestMethods(testMethod, testMthdInst.getInstance(), m_testContext);
} finally {
invokeAfterClassMethods(testClass, testMthdInst);
}
}
}
protected void invokeTestMethods(ITestNGMethod tm, Object instance,
ITestContext testContext)
{
// Potential bug here: we look up the method index of tm among all
// the test methods (not very efficient) but if this method appears
// several times and these methods are run in parallel, the results
// are unpredictable... Need to think about this more (and make it
// more efficient)
List testResults =
m_invoker.invokeTestMethods(tm,
m_suite,
m_parameters,
m_groupMethods,
instance,
testContext);
if (testResults != null) {
m_testResults.addAll(testResults);
}
}
/**
* Invoke the @BeforeClass methods if not done already
* @param testClass
* @param mi
*/
protected void invokeBeforeClassMethods(ITestClass testClass, IMethodInstance mi) {
// if no BeforeClass than return immediately
// used for parallel case when BeforeClass were already invoked
if (m_classMethodMap == null) {
return;
}
// the whole invocation must be synchronized as other threads must
// get a full initialized test object (not the same for @After)
Map> invokedBeforeClassMethods = m_classMethodMap.getInvokedBeforeClassMethods();
Set