0001: package org.testng;
0002:
0003: import java.io.File;
0004: import java.util.ArrayList;
0005: import java.util.Collection;
0006: import java.util.Collections;
0007: import java.util.Date;
0008: import java.util.HashMap;
0009: import java.util.List;
0010: import java.util.Map;
0011: import java.util.Set;
0012: import java.util.regex.Pattern;
0013:
0014: import org.testng.internal.ClassHelper;
0015: import org.testng.internal.ConfigurationGroupMethods;
0016: import org.testng.internal.Constants;
0017: import org.testng.internal.IConfigurationListener;
0018: import org.testng.internal.IInvoker;
0019: import org.testng.internal.IMethodWorker;
0020: import org.testng.internal.ITestResultNotifier;
0021: import org.testng.internal.InvokedMethod;
0022: import org.testng.internal.Invoker;
0023: import org.testng.internal.MethodHelper;
0024: import org.testng.internal.MethodInstance;
0025: import org.testng.internal.ResultMap;
0026: import org.testng.internal.RunInfo;
0027: import org.testng.internal.TestMethodWorker;
0028: import org.testng.internal.TestNGClassFinder;
0029: import org.testng.internal.TestNGMethodFinder;
0030: import org.testng.internal.Utils;
0031: import org.testng.internal.XmlMethodSelector;
0032: import org.testng.internal.annotations.IAnnotationFinder;
0033: import org.testng.internal.thread.ThreadUtil;
0034: import org.testng.junit.IJUnitTestRunner;
0035: import org.testng.xml.XmlClass;
0036: import org.testng.xml.XmlPackage;
0037: import org.testng.xml.XmlSuite;
0038: import org.testng.xml.XmlTest;
0039:
0040: /**
0041: * This class takes care of running one Test.
0042: *
0043: * @author Cedric Beust, Apr 26, 2004
0044: * @author <a href = "mailto:the_mindstorm@evolva.ro">Alexandru Popescu</a>
0045: */
0046: public class TestRunner implements ITestContext, ITestResultNotifier {
0047: /* generated */
0048: private static final long serialVersionUID = 4247820024988306670L;
0049: private ISuite m_suite;
0050: protected XmlTest m_xmlTest;
0051: private String m_testName;
0052:
0053: transient private List<XmlClass> m_testClassesFromXml = null;
0054: transient private List<XmlPackage> m_packageNamesFromXml = null;
0055:
0056: transient private IInvoker m_invoker = null;
0057: transient private IAnnotationFinder m_annotationFinder = null;
0058:
0059: /** ITestListeners support. */
0060: transient private List<ITestListener> m_testListeners = new ArrayList<ITestListener>();
0061: transient private List<IConfigurationListener> m_configurationListeners = new ArrayList<IConfigurationListener>();
0062:
0063: transient private IConfigurationListener m_confListener = new ConfigurationListener();
0064: transient private boolean m_skipFailedInvocationCounts;
0065:
0066: /**
0067: * All the test methods we found, associated with their respective classes.
0068: * Note that these test methods might belong to different classes.
0069: * We pick which ones to run at runtime.
0070: */
0071: private ITestNGMethod[] m_allTestMethods = new ITestNGMethod[0];
0072:
0073: // Information about this test run
0074:
0075: private Date m_startDate = null;
0076: private Date m_endDate = null;
0077:
0078: /** A map to keep track of Class <-> IClass. */
0079: transient private Map<Class<?>, ITestClass> m_classMap = new HashMap<Class<?>, ITestClass>();
0080:
0081: /** Where the reports will be created. */
0082: private String m_outputDirectory = Constants
0083: .getDefaultValueFor(Constants.PROP_OUTPUT_DIR);
0084:
0085: // The XML method selector (groups/methods included/excluded in XML)
0086: private XmlMethodSelector m_xmlMethodSelector = new XmlMethodSelector();
0087:
0088: private static int m_verbose = 1;
0089:
0090: //
0091: // These next fields contain all the configuration methods found on this class.
0092: // At initialization time, they just contain all the various @Configuration methods
0093: // found in all the classes we are going to run. When comes the time to run them,
0094: // only a subset of them are run: those that are enabled and belong on the same class as
0095: // (or a parent of) the test class.
0096: //
0097: /** */
0098: private ITestNGMethod[] m_beforeSuiteMethods = {};
0099: private ITestNGMethod[] m_afterSuiteMethods = {};
0100: private ITestNGMethod[] m_beforeXmlTestMethods = {};
0101: private ITestNGMethod[] m_afterXmlTestMethods = {};
0102: private List<ITestNGMethod> m_excludedMethods = new ArrayList<ITestNGMethod>();
0103: private ConfigurationGroupMethods m_groupMethods = null;
0104:
0105: // Meta groups
0106: private Map<String, List<String>> m_metaGroups = new HashMap<String, List<String>>();
0107:
0108: // All the tests that were run along with their result
0109: private IResultMap m_passedTests = new ResultMap();
0110: private IResultMap m_failedTests = new ResultMap();
0111: private IResultMap m_failedButWithinSuccessPercentageTests = new ResultMap();
0112: private IResultMap m_skippedTests = new ResultMap();
0113:
0114: private RunInfo m_runInfo = new RunInfo();
0115:
0116: // The host where this test was run, or null if run locally
0117: private String m_host;
0118:
0119: private Map<String, Object> m_attributes = new HashMap<String, Object>();
0120:
0121: public TestRunner(ISuite suite, XmlTest test,
0122: String outputDirectory, IAnnotationFinder finder,
0123: boolean skipFailedInvocationCounts) {
0124: init(suite, test, outputDirectory, finder,
0125: skipFailedInvocationCounts);
0126: }
0127:
0128: public TestRunner(ISuite suite, XmlTest test,
0129: IAnnotationFinder finder, boolean skipFailedInvocationCounts) {
0130: init(suite, test, suite.getOutputDirectory(), finder,
0131: skipFailedInvocationCounts);
0132: }
0133:
0134: public TestRunner(ISuite suite, XmlTest test,
0135: boolean skipFailedInvocationCounts) {
0136: init(suite, test, suite.getOutputDirectory(), suite
0137: .getAnnotationFinder(test.getAnnotations()),
0138: skipFailedInvocationCounts);
0139: }
0140:
0141: private void init(ISuite suite, XmlTest test,
0142: String outputDirectory, IAnnotationFinder annotationFinder,
0143: boolean skipFailedInvocationCounts) {
0144: m_xmlTest = test;
0145: m_suite = suite;
0146: m_testName = test.getName();
0147: m_host = suite.getHost();
0148: m_testClassesFromXml = test.getXmlClasses();
0149: m_skipFailedInvocationCounts = skipFailedInvocationCounts;
0150:
0151: m_packageNamesFromXml = test.getXmlPackages();
0152: if (null != m_packageNamesFromXml) {
0153: for (XmlPackage xp : m_packageNamesFromXml) {
0154: m_testClassesFromXml.addAll(xp.getXmlClasses());
0155: }
0156: }
0157:
0158: m_annotationFinder = annotationFinder;
0159: m_invoker = new Invoker(this , this , m_suite.getSuiteState(),
0160: m_annotationFinder, m_skipFailedInvocationCounts);
0161:
0162: setVerbose(test.getVerbose());
0163:
0164: if (suite.getParallel() != null) {
0165: log(3, "Running the tests in '" + test.getName()
0166: + "' with parallel mode:" + suite.getParallel());
0167: }
0168:
0169: setOutputDirectory(outputDirectory);
0170:
0171: // Finish our initialization
0172: init();
0173: }
0174:
0175: public IInvoker getInvoker() {
0176: return m_invoker;
0177: }
0178:
0179: public ITestNGMethod[] getBeforeSuiteMethods() {
0180: return m_beforeSuiteMethods;
0181: }
0182:
0183: public ITestNGMethod[] getAfterSuiteMethods() {
0184: return m_afterSuiteMethods;
0185: }
0186:
0187: public ITestNGMethod[] getBeforeTestConfigurationMethods() {
0188: return m_beforeXmlTestMethods;
0189: }
0190:
0191: public ITestNGMethod[] getAfterTestConfigurationMethods() {
0192: return m_afterXmlTestMethods;
0193: }
0194:
0195: public Object getAttribute(String name) {
0196: return m_attributes.get(name);
0197: }
0198:
0199: public void setAttribute(String name, Object value) {
0200: m_attributes.put(name, value);
0201: }
0202:
0203: private void init() {
0204: initMetaGroups(m_xmlTest);
0205: initRunInfo(m_xmlTest);
0206:
0207: // Init methods and class map
0208: // JUnit behavior is different and doesn't need this initialization step
0209: if (!m_xmlTest.isJUnit()) {
0210: initMethods();
0211: }
0212:
0213: addConfigurationListener(m_confListener);
0214: }
0215:
0216: /**
0217: * Initialize meta groups
0218: */
0219: private void initMetaGroups(XmlTest xmlTest) {
0220: Map<String, List<String>> metaGroups = xmlTest.getMetaGroups();
0221:
0222: for (String name : metaGroups.keySet()) {
0223: addMetaGroup(name, metaGroups.get(name));
0224: }
0225: }
0226:
0227: private void initRunInfo(final XmlTest xmlTest) {
0228: // Groups
0229: m_xmlMethodSelector.setIncludedGroups(createGroups(m_xmlTest
0230: .getIncludedGroups()));
0231: m_xmlMethodSelector.setExcludedGroups(createGroups(m_xmlTest
0232: .getExcludedGroups()));
0233: m_xmlMethodSelector.setExpression(m_xmlTest.getExpression());
0234:
0235: // Methods
0236: m_xmlMethodSelector.setXmlClasses(m_xmlTest.getXmlClasses());
0237:
0238: m_runInfo.addMethodSelector(m_xmlMethodSelector, 10);
0239:
0240: // Add user-specified method selectors (only class selectors, we can ignore
0241: // script selectors here)
0242: if (null != xmlTest.getMethodSelectors()) {
0243: for (org.testng.xml.XmlMethodSelector selector : xmlTest
0244: .getMethodSelectors()) {
0245: if (selector.getClassName() != null) {
0246: IMethodSelector s = ClassHelper
0247: .createSelector(selector);
0248:
0249: m_runInfo.addMethodSelector(s, selector
0250: .getPriority());
0251: }
0252: }
0253: }
0254: }
0255:
0256: private void initMethods() {
0257:
0258: //
0259: // Calculate all the methods we need to invoke
0260: //
0261: List<ITestNGMethod> beforeClassMethods = new ArrayList<ITestNGMethod>();
0262: List<ITestNGMethod> testMethods = new ArrayList<ITestNGMethod>();
0263: List<ITestNGMethod> afterClassMethods = new ArrayList<ITestNGMethod>();
0264: List<ITestNGMethod> beforeSuiteMethods = new ArrayList<ITestNGMethod>();
0265: List<ITestNGMethod> afterSuiteMethods = new ArrayList<ITestNGMethod>();
0266: List<ITestNGMethod> beforeXmlTestMethods = new ArrayList<ITestNGMethod>();
0267: List<ITestNGMethod> afterXmlTestMethods = new ArrayList<ITestNGMethod>();
0268:
0269: ITestClassFinder testClassFinder = new TestNGClassFinder(Utils
0270: .xmlClassesToClasses(m_testClassesFromXml), null,
0271: m_xmlTest, m_annotationFinder, this );
0272: ITestMethodFinder testMethodFinder = new TestNGMethodFinder<ITestNGMethod>(
0273: m_runInfo, m_annotationFinder);
0274:
0275: m_runInfo.setTestMethods(testMethods);
0276:
0277: //
0278: // Initialize TestClasses
0279: //
0280: IClass[] classes = testClassFinder.findTestClasses();
0281:
0282: for (IClass ic : classes) {
0283:
0284: // Create TestClass
0285: ITestClass tc = new TestClass(ic, m_testName,
0286: testMethodFinder, m_annotationFinder, m_runInfo);
0287: m_classMap.put(ic.getRealClass(), tc);
0288: }
0289:
0290: //
0291: // Calculate groups methods
0292: //
0293: Map<String, List<ITestNGMethod>> beforeGroupMethods = MethodHelper
0294: .findGroupsMethods(m_classMap.values(), true);
0295: Map<String, List<ITestNGMethod>> afterGroupMethods = MethodHelper
0296: .findGroupsMethods(m_classMap.values(), false);
0297:
0298: //
0299: // Walk through all the TestClasses, store their method
0300: // and initialize them with the correct ITestClass
0301: //
0302: for (ITestClass tc : m_classMap.values()) {
0303: fixMethodsWithClass(tc.getBeforeClassMethods(), tc,
0304: beforeClassMethods);
0305: fixMethodsWithClass(tc.getBeforeTestMethods(), tc, null); // HINT: does not link back to beforeTestMethods
0306: fixMethodsWithClass(tc.getTestMethods(), tc, testMethods);
0307: fixMethodsWithClass(tc.getAfterTestMethods(), tc, null);
0308: fixMethodsWithClass(tc.getAfterClassMethods(), tc,
0309: afterClassMethods);
0310: fixMethodsWithClass(tc.getBeforeSuiteMethods(), tc,
0311: beforeSuiteMethods);
0312: fixMethodsWithClass(tc.getAfterSuiteMethods(), tc,
0313: afterSuiteMethods);
0314: fixMethodsWithClass(tc.getBeforeTestConfigurationMethods(),
0315: tc, beforeXmlTestMethods);
0316: fixMethodsWithClass(tc.getAfterTestConfigurationMethods(),
0317: tc, afterXmlTestMethods);
0318: fixMethodsWithClass(tc.getBeforeGroupsMethods(), tc,
0319: MethodHelper.uniqueMethodList(beforeGroupMethods
0320: .values()));
0321: fixMethodsWithClass(tc.getAfterGroupsMethods(), tc,
0322: MethodHelper.uniqueMethodList(afterGroupMethods
0323: .values()));
0324: }
0325:
0326: //
0327: // Sort the methods
0328: //
0329: m_beforeSuiteMethods = MethodHelper
0330: .collectAndOrderConfigurationMethods(
0331: beforeSuiteMethods, m_runInfo,
0332: m_annotationFinder, true /* unique */,
0333: m_excludedMethods);
0334:
0335: m_beforeXmlTestMethods = MethodHelper
0336: .collectAndOrderConfigurationMethods(
0337: beforeXmlTestMethods, m_runInfo,
0338: m_annotationFinder, true, // CQ added by me
0339: m_excludedMethods);
0340:
0341: m_allTestMethods = MethodHelper.collectAndOrderMethods(
0342: testMethods, m_runInfo, m_annotationFinder,
0343: m_excludedMethods);
0344:
0345: m_afterXmlTestMethods = MethodHelper
0346: .collectAndOrderConfigurationMethods(
0347: afterXmlTestMethods, m_runInfo,
0348: m_annotationFinder, true, // CQ added by me
0349: m_excludedMethods);
0350:
0351: m_afterSuiteMethods = MethodHelper
0352: .collectAndOrderConfigurationMethods(afterSuiteMethods,
0353: m_runInfo, m_annotationFinder,
0354: true /* unique */, m_excludedMethods);
0355: // shared group methods
0356: m_groupMethods = new ConfigurationGroupMethods(
0357: m_allTestMethods, beforeGroupMethods, afterGroupMethods);
0358: }
0359:
0360: private void fixMethodsWithClass(ITestNGMethod[] methods,
0361: ITestClass testCls, List<ITestNGMethod> methodList) {
0362: for (ITestNGMethod itm : methods) {
0363: itm.setTestClass(testCls);
0364:
0365: if (methodList != null) {
0366: methodList.add(itm);
0367: }
0368: }
0369: }
0370:
0371: public Collection<ITestClass> getIClass() {
0372: return m_classMap.values();
0373: }
0374:
0375: public void setTestName(String name) {
0376: m_testName = name;
0377: }
0378:
0379: public void setOutputDirectory(String od) {
0380: m_outputDirectory = od;
0381: // FIX: empty directories were created
0382: // if (od == null) { m_outputDirectory = null; return; } //for maven2
0383: // File file = new File(od);
0384: // file.mkdirs();
0385: // m_outputDirectory= file.getAbsolutePath();
0386: }
0387:
0388: private void addMetaGroup(String name, List<String> groupNames) {
0389: m_metaGroups.put(name, groupNames);
0390: }
0391:
0392: /**
0393: * Calculate the transitive closure of all the MetaGroups
0394: *
0395: * @param groups
0396: * @param unfinishedGroups
0397: * @param result The transitive closure containing all the groups found
0398: */
0399: private void collectGroups(String[] groups,
0400: List<String> unfinishedGroups, Map<String, String> result) {
0401: for (String gn : groups) {
0402: List<String> subGroups = m_metaGroups.get(gn);
0403: if (null != subGroups) {
0404:
0405: for (String sg : subGroups) {
0406: if (null == result.get(sg)) {
0407: result.put(sg, sg);
0408: unfinishedGroups.add(sg);
0409: }
0410: }
0411: }
0412: }
0413: }
0414:
0415: private Map<String, String> createGroups(List<String> groups) {
0416: return createGroups((String[]) groups.toArray(new String[groups
0417: .size()]));
0418: }
0419:
0420: private Map<String, String> createGroups(String[] groups) {
0421: Map<String, String> result = new HashMap<String, String>();
0422:
0423: // Groups that were passed on the command line
0424: for (String group : groups) {
0425: result.put(group, group);
0426: }
0427:
0428: // See if we have any MetaGroups and
0429: // expand them if they match one of the groups
0430: // we have just been passed
0431: List<String> unfinishedGroups = new ArrayList<String>();
0432:
0433: if (m_metaGroups.size() > 0) {
0434: collectGroups(groups, unfinishedGroups, result);
0435:
0436: // Do we need to loop over unfinished groups?
0437: while (unfinishedGroups.size() > 0) {
0438: String[] uGroups = (String[]) unfinishedGroups
0439: .toArray(new String[unfinishedGroups.size()]);
0440: unfinishedGroups = new ArrayList<String>();
0441: collectGroups(uGroups, unfinishedGroups, result);
0442: }
0443: }
0444:
0445: // Utils.dumpMap(result);
0446: return result;
0447: }
0448:
0449: /**
0450: * The main entry method for TestRunner.
0451: *
0452: * This is where all the hard work is done:
0453: * - Invoke configuration methods
0454: * - Invoke test methods
0455: * - Catch exceptions
0456: * - Collect results
0457: * - Invoke listeners
0458: * - etc...
0459: */
0460: public void run() {
0461: beforeRun();
0462:
0463: try {
0464: XmlTest test = getTest();
0465: if (test.isJUnit()) {
0466: privateRunJUnit(test);
0467: } else {
0468: privateRun(test);
0469: }
0470: } finally {
0471: afterRun();
0472: }
0473: }
0474:
0475: /** Before run preparements. */
0476: private void beforeRun() {
0477: //
0478: // Log the start date
0479: //
0480: m_startDate = new Date(System.currentTimeMillis());
0481:
0482: // Log start
0483: logStart();
0484:
0485: // Invoke listeners
0486: fireEvent(true /*start*/);
0487:
0488: // invoke @BeforeTest
0489: ITestNGMethod[] testConfigurationMethods = getBeforeTestConfigurationMethods();
0490: if (null != testConfigurationMethods
0491: && testConfigurationMethods.length > 0) {
0492: m_invoker.invokeConfigurations(null,
0493: testConfigurationMethods, m_xmlTest.getSuite(),
0494: m_xmlTest.getParameters(), null /* instance */);
0495: }
0496: }
0497:
0498: private void privateRunJUnit(XmlTest xmlTest) {
0499: final Class<?>[] classes = Utils
0500: .xmlClassesToClasses(m_testClassesFromXml);
0501: final List<ITestNGMethod> runMethods = new ArrayList<ITestNGMethod>();
0502: List<IMethodWorker> workers = new ArrayList<IMethodWorker>();
0503: // FIXME: directly referincing JUnitTestRunner which uses JUnit classes
0504: // may result in an class resolution exception under different JVMs
0505: // The resolution process is not specified in the JVM spec with a specific implementation,
0506: // so it can be eager => failure
0507: workers.add(new IMethodWorker() {
0508: /**
0509: * @see org.testng.internal.IMethodWorker#getMaxTimeOut()
0510: */
0511: public long getMaxTimeOut() {
0512: return 0;
0513: }
0514:
0515: public List<ITestResult> getTestResults() {
0516: return null;
0517: }
0518:
0519: /**
0520: * @see java.lang.Runnable#run()
0521: */
0522: public void run() {
0523: for (Class<?> tc : classes) {
0524: IJUnitTestRunner tr = ClassHelper
0525: .createTestRunner(TestRunner.this );
0526: try {
0527: tr.run(tc);
0528: } catch (Exception ex) {
0529: ex.printStackTrace();
0530: } finally {
0531: runMethods.addAll(tr.getTestMethods());
0532: }
0533: }
0534: }
0535: });
0536:
0537: runWorkers(workers, "" /* JUnit does not support parallel */);
0538: m_allTestMethods = runMethods
0539: .toArray(new ITestNGMethod[runMethods.size()]);
0540: }
0541:
0542: public void privateRun(XmlTest xmlTest) {
0543: //
0544: // Calculate the lists of tests that can be run in sequence and in parallel
0545: //
0546: List<List<ITestNGMethod>> sequentialList = new ArrayList<List<ITestNGMethod>>();
0547: List<ITestNGMethod> parallelList = new ArrayList<ITestNGMethod>();
0548:
0549: computeTestLists(sequentialList, parallelList);
0550:
0551: log(3, "Found " + (sequentialList.size() + parallelList.size())
0552: + " applicable methods");
0553:
0554: //
0555: // Create the workers
0556: //
0557: List<TestMethodWorker> workers = new ArrayList<TestMethodWorker>();
0558:
0559: ClassMethodMap cmm = new ClassMethodMap(m_allTestMethods);
0560:
0561: createSequentialWorkers(sequentialList,
0562: xmlTest.getParameters(), cmm, workers);
0563:
0564: // All the parallel tests are placed in a separate worker, so they can be
0565: // invoked in parallel
0566: createParallelWorkers(parallelList, xmlTest.getParameters(),
0567: cmm, workers);
0568:
0569: try {
0570: runWorkers(workers, xmlTest.getParallel());
0571: } finally {
0572: cmm.clear();
0573: }
0574: }
0575:
0576: private void createParallelWorkers(List<ITestNGMethod> parallel,
0577: Map<String, String> params, ClassMethodMap cmm,
0578: List<TestMethodWorker> workers) {
0579:
0580: if (parallel.isEmpty())
0581: return;
0582:
0583: List<MethodInstance> methodInstances = new ArrayList<MethodInstance>();
0584: for (ITestNGMethod tm : parallel) {
0585: methodInstances
0586: .addAll(methodsToMultipleMethodInstances(tm));
0587: }
0588:
0589: //
0590: // Finally, sort the parallel methods by classes
0591: //
0592: Collections.sort(methodInstances, MethodInstance.SORT_BY_CLASS);
0593:
0594: if (getVerbose() >= 2) {
0595: log(3, "WILL BE RUN IN RANDOM ORDER:");
0596: for (MethodInstance mi : methodInstances) {
0597: log(3, " " + mi.getMethod());
0598: log(3, " on instances");
0599: for (Object o : mi.getInstances()) {
0600: log(3, " " + o);
0601: }
0602: }
0603: log(3, "===");
0604: }
0605:
0606: for (MethodInstance mi : methodInstances) {
0607: workers
0608: .add(new TestMethodWorker(m_invoker,
0609: new MethodInstance[] { mi }, m_xmlTest
0610: .getSuite(), params,
0611: m_allTestMethods, m_groupMethods, cmm, this ));
0612: }
0613:
0614: }
0615:
0616: private void createSequentialWorkers(
0617: List<List<ITestNGMethod>> sequentialList,
0618: Map<String, String> params, ClassMethodMap cmm,
0619: List<TestMethodWorker> workers) {
0620: if (sequentialList.isEmpty())
0621: return;
0622:
0623: // All the sequential tests are place in one worker, guaranteeing they
0624: // will be invoked sequentially
0625: for (List<ITestNGMethod> sl : sequentialList) {
0626: workers
0627: .add(new TestMethodWorker(m_invoker,
0628: methodsToMethodInstances(sl), m_xmlTest
0629: .getSuite(), params,
0630: m_allTestMethods, m_groupMethods, cmm, this ));
0631: }
0632: if (getVerbose() >= 2) {
0633: log(3, "WILL BE RUN SEQUENTIALLY:");
0634: for (List<ITestNGMethod> l : sequentialList) {
0635: for (ITestNGMethod tm : l) {
0636: log(3, " " + tm);
0637: }
0638: log(3, "====");
0639: }
0640:
0641: log(3, "===");
0642: }
0643: }
0644:
0645: private List<MethodInstance> methodsToMultipleMethodInstances(
0646: ITestNGMethod... sl) {
0647: List<MethodInstance> vResult = new ArrayList<MethodInstance>();
0648: for (ITestNGMethod m : sl) {
0649: Object[] instances = m.getTestClass().getInstances(true);
0650: for (Object instance : instances) {
0651: vResult.add(new MethodInstance(m,
0652: new Object[] { instance }));
0653: }
0654: }
0655:
0656: return vResult;
0657: }
0658:
0659: private MethodInstance[] methodsToMethodInstances(
0660: List<ITestNGMethod> sl) {
0661: MethodInstance[] result = new MethodInstance[sl.size()];
0662: for (int i = 0; i < result.length; i++) {
0663: result[i] = new MethodInstance(sl.get(i), sl.get(i)
0664: .getTestClass().getInstances(true));
0665: }
0666:
0667: return result;
0668: }
0669:
0670: //
0671: // Invoke the workers
0672: //
0673: private void runWorkers(List<? extends IMethodWorker> workers,
0674: String parallelMode) {
0675: if (XmlSuite.PARALLEL_METHODS.equals(parallelMode)
0676: || "true".equalsIgnoreCase(parallelMode)) {
0677: //
0678: // Parallel run
0679: //
0680: // Default timeout for individual methods: 10 seconds
0681: long maxTimeOut = m_xmlTest.getTimeOut(10 * 1000);
0682: for (IMethodWorker tmw : workers) {
0683: long mt = tmw.getMaxTimeOut();
0684: if (mt > maxTimeOut) {
0685: maxTimeOut = mt;
0686: }
0687: }
0688:
0689: ThreadUtil.execute(workers, m_xmlTest.getThreadCount(),
0690: maxTimeOut, false);
0691: } else {
0692: //
0693: // Sequential run
0694: //
0695: for (IMethodWorker tmw : workers) {
0696: tmw.run();
0697: }
0698: }
0699: }
0700:
0701: private void afterRun() {
0702: // invoke @AfterTest
0703: ITestNGMethod[] testConfigurationMethods = getAfterTestConfigurationMethods();
0704: if (null != testConfigurationMethods
0705: && testConfigurationMethods.length > 0) {
0706: m_invoker.invokeConfigurations(null,
0707: testConfigurationMethods, m_xmlTest.getSuite(),
0708: m_xmlTest.getParameters(), null /* instance */);
0709: }
0710:
0711: //
0712: // Log the end date
0713: //
0714: m_endDate = new Date(System.currentTimeMillis());
0715:
0716: if (getVerbose() >= 3) {
0717: dumpInvokedMethods();
0718: }
0719:
0720: // Invoke listeners
0721: fireEvent(false /*stop*/);
0722:
0723: // Statistics
0724: // logResults();
0725: }
0726:
0727: /**
0728: * @param regexps
0729: * @param group
0730: * @return true if the map contains at least one regexp that matches the
0731: * given group
0732: */
0733: private boolean containsString(Map<String, String> regexps,
0734: String group) {
0735: for (String regexp : regexps.values()) {
0736: boolean match = Pattern.matches(regexp, group);
0737: if (match) {
0738: return true;
0739: }
0740: }
0741:
0742: return false;
0743: }
0744:
0745: /**
0746: * Creates the
0747: * @param sl the sequential list of methods
0748: * @param parallelList the list of methods that can be run in parallel
0749: */
0750: private void computeTestLists(List<List<ITestNGMethod>> sl,
0751: List<ITestNGMethod> parallelList) {
0752:
0753: Map<String, String> groupsDependedUpon = new HashMap<String, String>();
0754: Map<String, String> methodsDependedUpon = new HashMap<String, String>();
0755:
0756: Map<String, List<ITestNGMethod>> sequentialAttributeList = new HashMap<String, List<ITestNGMethod>>();
0757: List<ITestNGMethod> sequentialList = new ArrayList<ITestNGMethod>();
0758:
0759: for (int i = m_allTestMethods.length - 1; i >= 0; i--) {
0760: ITestNGMethod tm = m_allTestMethods[i];
0761:
0762: //
0763: // If the class this method belongs to has @Test(sequential = true), we
0764: // put this method in the sequential list right away
0765: //
0766: Class<?> cls = tm.getRealClass();
0767: org.testng.internal.annotations.ITest test = (org.testng.internal.annotations.ITest) m_annotationFinder
0768: .findAnnotation(cls,
0769: org.testng.internal.annotations.ITest.class);
0770: if (test != null) {
0771: if (test.getSequential()) {
0772: String className = cls.getName();
0773: List<ITestNGMethod> list = sequentialAttributeList
0774: .get(className);
0775: if (list == null) {
0776: list = new ArrayList<ITestNGMethod>();
0777: sequentialAttributeList.put(className, list);
0778: }
0779: list.add(0, tm);
0780: continue;
0781: }
0782: }
0783:
0784: //
0785: // Otherwise, determine if it depends on other methods/groups or if
0786: // it is depended upon
0787: //
0788: String[] currentGroups = tm.getGroups();
0789: String[] currentGroupsDependedUpon = tm
0790: .getGroupsDependedUpon();
0791: String[] currentMethodsDependedUpon = tm
0792: .getMethodsDependedUpon();
0793:
0794: String this MethodName = tm.getMethod().getDeclaringClass()
0795: .getName()
0796: + "." + tm.getMethod().getName();
0797: if (currentGroupsDependedUpon.length > 0) {
0798: for (String gdu : currentGroupsDependedUpon) {
0799: groupsDependedUpon.put(gdu, gdu);
0800: }
0801:
0802: sequentialList.add(0, tm);
0803: } else if (currentMethodsDependedUpon.length > 0) {
0804: for (String cmu : currentMethodsDependedUpon) {
0805: methodsDependedUpon.put(cmu, cmu);
0806: }
0807: sequentialList.add(0, tm);
0808: }
0809: // Is there a method that depends on the current method?
0810: else if (containsString(methodsDependedUpon, this MethodName)) {
0811: sequentialList.add(0, tm);
0812: } else if (currentGroups.length > 0) {
0813: boolean isSequential = false;
0814:
0815: for (String group : currentGroups) {
0816: if (containsString(groupsDependedUpon, group)) {
0817: sequentialList.add(0, tm);
0818: isSequential = true;
0819:
0820: break;
0821: }
0822: }
0823: if (!isSequential) {
0824: parallelList.add(0, tm);
0825: }
0826: } else {
0827: parallelList.add(0, tm);
0828: }
0829: }
0830:
0831: //
0832: // Put all the sequential methods in the output argument
0833: //
0834: if (sequentialList.size() > 0) {
0835: sl.add(sequentialList);
0836: }
0837:
0838: sl.addAll(sequentialAttributeList.values());
0839: }
0840:
0841: /**
0842: * Logs the beginning of the {@link #beforeRun()} .
0843: */
0844: private void logStart() {
0845: log(3, "Running test " + m_testName + " on "
0846: + m_classMap.size() + " " + " classes, "
0847: + " included groups:["
0848: + mapToString(m_xmlMethodSelector.getIncludedGroups())
0849: + "] excluded groups:["
0850: + mapToString(m_xmlMethodSelector.getExcludedGroups())
0851: + "]");
0852:
0853: if (getVerbose() >= 3) {
0854: for (ITestClass tc : m_classMap.values()) {
0855: ((TestClass) tc).dump();
0856: }
0857: }
0858: }
0859:
0860: /**
0861: * Trigger the start/finish event.
0862: *
0863: * @param isStart <tt>true</tt> if the event is for start, <tt>false</tt> if the
0864: * event is for finish
0865: */
0866: private void fireEvent(boolean isStart) {
0867: for (ITestListener itl : m_testListeners) {
0868: if (isStart) {
0869: itl.onStart(this );
0870: } else {
0871: itl.onFinish(this );
0872: }
0873: }
0874: }
0875:
0876: /////
0877: // ITestContext
0878: //
0879: public String getName() {
0880: return m_testName;
0881: }
0882:
0883: /**
0884: * @return Returns the startDate.
0885: */
0886: public Date getStartDate() {
0887: return m_startDate;
0888: }
0889:
0890: /**
0891: * @return Returns the endDate.
0892: */
0893: public Date getEndDate() {
0894: return m_endDate;
0895: }
0896:
0897: public IResultMap getPassedTests() {
0898: return m_passedTests;
0899: }
0900:
0901: public IResultMap getSkippedTests() {
0902: return m_skippedTests;
0903: }
0904:
0905: public IResultMap getFailedTests() {
0906: return m_failedTests;
0907: }
0908:
0909: public IResultMap getFailedButWithinSuccessPercentageTests() {
0910: return m_failedButWithinSuccessPercentageTests;
0911: }
0912:
0913: public String[] getIncludedGroups() {
0914: Map<String, String> ig = m_xmlMethodSelector
0915: .getIncludedGroups();
0916: String[] result = (String[]) ig.values().toArray(
0917: (new String[ig.size()]));
0918:
0919: return result;
0920: }
0921:
0922: public String[] getExcludedGroups() {
0923: Map<String, String> eg = m_xmlMethodSelector
0924: .getExcludedGroups();
0925: String[] result = (String[]) eg.values().toArray(
0926: (new String[eg.size()]));
0927:
0928: return result;
0929: }
0930:
0931: public String getOutputDirectory() {
0932: return m_outputDirectory;
0933: }
0934:
0935: /**
0936: * @return Returns the suite.
0937: */
0938: public ISuite getSuite() {
0939: return m_suite;
0940: }
0941:
0942: public ITestNGMethod[] getAllTestMethods() {
0943: return m_allTestMethods;
0944: }
0945:
0946: public String getHost() {
0947: return m_host;
0948: }
0949:
0950: public Collection<ITestNGMethod> getExcludedMethods() {
0951: Map<ITestNGMethod, ITestNGMethod> vResult = new HashMap<ITestNGMethod, ITestNGMethod>();
0952:
0953: for (ITestNGMethod m : m_excludedMethods) {
0954: vResult.put(m, m);
0955: }
0956:
0957: return vResult.keySet();
0958: }
0959:
0960: /**
0961: * @see org.testng.ITestContext#getFailedConfigurations()
0962: */
0963: public IResultMap getFailedConfigurations() {
0964: return m_failedConfigurations;
0965: }
0966:
0967: /**
0968: * @see org.testng.ITestContext#getPassedConfigurations()
0969: */
0970: public IResultMap getPassedConfigurations() {
0971: return m_passedConfigurations;
0972: }
0973:
0974: /**
0975: * @see org.testng.ITestContext#getSkippedConfigurations()
0976: */
0977: public IResultMap getSkippedConfigurations() {
0978: return m_skippedConfigurations;
0979: }
0980:
0981: //
0982: // ITestContext
0983: /////
0984:
0985: /////
0986: // ITestResultNotifier
0987: //
0988:
0989: public void addPassedTest(ITestNGMethod tm, ITestResult tr) {
0990: m_passedTests.addResult(tr, tm);
0991: }
0992:
0993: public Set<ITestResult> getPassedTests(ITestNGMethod tm) {
0994: return m_passedTests.getResults(tm);
0995: }
0996:
0997: public void addSkippedTest(ITestNGMethod tm, ITestResult tr) {
0998: m_skippedTests.addResult(tr, tm);
0999: }
1000:
1001: public void addInvokedMethod(InvokedMethod im) {
1002: synchronized (m_invokedMethods) {
1003: m_invokedMethods.add(im);
1004: }
1005: }
1006:
1007: public void addFailedTest(ITestNGMethod testMethod,
1008: ITestResult result) {
1009: logFailedTest(testMethod, result, false /* withinSuccessPercentage */);
1010: }
1011:
1012: public void addFailedButWithinSuccessPercentageTest(
1013: ITestNGMethod testMethod, ITestResult result) {
1014: logFailedTest(testMethod, result, true /* withinSuccessPercentage */);
1015: }
1016:
1017: public XmlTest getTest() {
1018: return m_xmlTest;
1019: }
1020:
1021: public List<ITestListener> getTestListeners() {
1022: return m_testListeners;
1023: }
1024:
1025: public List<IConfigurationListener> getConfigurationListeners() {
1026: return m_configurationListeners;
1027: }
1028:
1029: //
1030: // ITestResultNotifier
1031: /////
1032:
1033: private void logFailedTest(ITestNGMethod method, ITestResult tr,
1034: boolean withinSuccessPercentage) {
1035: if (withinSuccessPercentage) {
1036: m_failedButWithinSuccessPercentageTests.addResult(tr,
1037: method);
1038: } else {
1039: m_failedTests.addResult(tr, method);
1040: }
1041: }
1042:
1043: private String mapToString(Map<?, ?> m) {
1044: StringBuffer result = new StringBuffer();
1045: for (Object o : m.values()) {
1046: result.append(o.toString()).append(" ");
1047: }
1048:
1049: return result.toString();
1050: }
1051:
1052: private void log(int level, String s) {
1053: Utils.log("TestRunner", level, s);
1054: }
1055:
1056: public static int getVerbose() {
1057: return m_verbose;
1058: }
1059:
1060: public void setVerbose(int n) {
1061: m_verbose = n;
1062: }
1063:
1064: private void log(String s) {
1065: Utils.log("TestRunner", 2, s);
1066: }
1067:
1068: /////
1069: // Listeners
1070: //
1071: public void addListener(Object listener) {
1072: if (listener instanceof ITestListener) {
1073: addTestListener((ITestListener) listener);
1074: }
1075: if (listener instanceof IConfigurationListener) {
1076: addConfigurationListener((IConfigurationListener) listener);
1077: }
1078: }
1079:
1080: public void addTestListener(ITestListener il) {
1081: m_testListeners.add(il);
1082: }
1083:
1084: public void addConfigurationListener(IConfigurationListener icl) {
1085: m_configurationListeners.add(icl);
1086: }
1087:
1088: //
1089: // Listeners
1090: /////
1091:
1092: private List<InvokedMethod> m_invokedMethods = new ArrayList<InvokedMethod>();
1093:
1094: private void dumpInvokedMethods() {
1095: System.out.println("\n*********** INVOKED METHODS\n");
1096: for (InvokedMethod im : m_invokedMethods) {
1097: if (im.isTestMethod()) {
1098: System.out.print("\t\t");
1099: } else if (im.isConfigurationMethod()) {
1100: System.out.print("\t");
1101: } else {
1102: continue;
1103: }
1104: System.out.println("" + im);
1105: }
1106: System.out.println("\n***********\n");
1107: }
1108:
1109: /**
1110: * @return
1111: */
1112: public List<ITestNGMethod> getInvokedMethods() {
1113: List<ITestNGMethod> result = new ArrayList<ITestNGMethod>();
1114: for (InvokedMethod im : m_invokedMethods) {
1115: ITestNGMethod tm = im.getTestMethod();
1116: tm.setDate(im.getDate());
1117: result.add(tm);
1118: }
1119:
1120: return result;
1121: }
1122:
1123: private IResultMap m_passedConfigurations = new ResultMap();
1124: private IResultMap m_skippedConfigurations = new ResultMap();
1125: private IResultMap m_failedConfigurations = new ResultMap();
1126:
1127: private class ConfigurationListener implements
1128: IConfigurationListener {
1129: public void onConfigurationFailure(ITestResult itr) {
1130: m_failedConfigurations.addResult(itr, itr.getMethod());
1131: }
1132:
1133: public void onConfigurationSkip(ITestResult itr) {
1134: m_skippedConfigurations.addResult(itr, itr.getMethod());
1135: }
1136:
1137: public void onConfigurationSuccess(ITestResult itr) {
1138: m_passedConfigurations.addResult(itr, itr.getMethod());
1139: }
1140: }
1141: } // TestRunner
|