1 package org.testng; 2 3 import java.lang.annotation.Annotation; 4 import java.util.ArrayList; 5 import java.util.Arrays; 6 import java.util.Collection; 7 import java.util.Collections; 8 import java.util.Comparator; 9 import java.util.Date; 10 import java.util.EnumSet; 11 import java.util.List; 12 import java.util.Map; 13 import java.util.Set; 14 import java.util.concurrent.LinkedBlockingQueue; 15 import java.util.concurrent.TimeUnit; 16 17 import org.testng.annotations.Guice; 18 import org.testng.annotations.IListenersAnnotation; 19 import org.testng.collections.ListMultiMap; 20 import org.testng.collections.Lists; 21 import org.testng.collections.Maps; 22 import org.testng.collections.Sets; 23 import org.testng.internal.Attributes; 24 import org.testng.internal.ClassHelper; 25 import org.testng.internal.ClassImpl; 26 import org.testng.internal.ClassInfoMap; 27 import org.testng.internal.ConfigurationGroupMethods; 28 import org.testng.internal.Constants; 29 import org.testng.internal.DynamicGraph; 30 import org.testng.internal.DynamicGraph.Status; 31 import org.testng.internal.IConfiguration; 32 import org.testng.internal.IInvoker; 33 import org.testng.internal.ITestResultNotifier; 34 import org.testng.internal.InvokedMethod; 35 import org.testng.internal.Invoker; 36 import org.testng.internal.MethodGroupsHelper; 37 import org.testng.internal.MethodHelper; 38 import org.testng.internal.MethodInstance; 39 import org.testng.internal.ResultMap; 40 import org.testng.internal.RunInfo; 41 import org.testng.internal.TestMethodWorker; 42 import org.testng.internal.TestNGClassFinder; 43 import org.testng.internal.TestNGMethodFinder; 44 import org.testng.internal.Utils; 45 import org.testng.internal.XmlMethodSelector; 46 import org.testng.internal.annotations.AnnotationHelper; 47 import org.testng.internal.annotations.IAnnotationFinder; 48 import org.testng.internal.annotations.IListeners; 49 import org.testng.internal.thread.graph.GraphThreadPoolExecutor; 50 import org.testng.internal.thread.graph.IThreadWorkerFactory; 51 import org.testng.internal.thread.graph.IWorker; 52 import org.testng.junit.IJUnitTestRunner; 53 import org.testng.xml.XmlClass; 54 import org.testng.xml.XmlInclude; 55 import org.testng.xml.XmlPackage; 56 import org.testng.xml.XmlSuite; 57 import org.testng.xml.XmlTest; 58 59 import com.google.inject.Injector; 60 import com.google.inject.Module; 61 62 /** 63 * This class takes care of running one Test. 64 * 65 * @author Cedric Beust, Apr 26, 2004 66 */ 67 public class TestRunner 68 implements ITestContext, ITestResultNotifier, IThreadWorkerFactory<ITestNGMethod> 69 { 70 /* generated */ 71 private static final long serialVersionUID = 4247820024988306670L; 72 private ISuite m_suite; 73 private XmlTest m_xmlTest; 74 private String m_testName; 75 76 transient private List<XmlClass> m_testClassesFromXml= null; 77 transient private List<XmlPackage> m_packageNamesFromXml= null; 78 79 transient private IInvoker m_invoker= null; 80 transient private IAnnotationFinder m_annotationFinder= null; 81 82 /** ITestListeners support. */ 83 transient private List<ITestListener> m_testListeners = Lists.newArrayList(); 84 transient private Set<IConfigurationListener> m_configurationListeners = Sets.newHashSet(); 85 86 transient private IConfigurationListener m_confListener= new ConfigurationListener(); 87 transient private boolean m_skipFailedInvocationCounts; 88 89 transient private Collection<IInvokedMethodListener> m_invokedMethodListeners = Lists.newArrayList(); 90 transient private List<IClassListener> m_classListeners = Lists.newArrayList(); 91 92 /** 93 * All the test methods we found, associated with their respective classes. 94 * Note that these test methods might belong to different classes. 95 * We pick which ones to run at runtime. 96 */ 97 private ITestNGMethod[] m_allTestMethods = new ITestNGMethod[0]; 98 99 // Information about this test run 100 101 private Date m_startDate = null; 102 private Date m_endDate = null; 103 104 /** A map to keep track of Class <-> IClass. */ 105 transient private Map<Class<?>, ITestClass> m_classMap = Maps.newLinkedHashMap(); 106 107 /** Where the reports will be created. */ 108 private String m_outputDirectory= Constants.getDefaultValueFor(Constants.PROP_OUTPUT_DIR); 109 110 // The XML method selector (groups/methods included/excluded in XML) 111 private XmlMethodSelector m_xmlMethodSelector = new XmlMethodSelector(); 112 113 private static int m_verbose = 1; 114 115 // 116 // These next fields contain all the configuration methods found on this class. 117 // At initialization time, they just contain all the various @Configuration methods 118 // found in all the classes we are going to run. When comes the time to run them, 119 // only a subset of them are run: those that are enabled and belong on the same class as 120 // (or a parent of) the test class. 121 // 122 /** */ 123 private ITestNGMethod[] m_beforeSuiteMethods = {}; 124 private ITestNGMethod[] m_afterSuiteMethods = {}; 125 private ITestNGMethod[] m_beforeXmlTestMethods = {}; 126 private ITestNGMethod[] m_afterXmlTestMethods = {}; 127 private List<ITestNGMethod> m_excludedMethods = Lists.newArrayList(); 128 private ConfigurationGroupMethods m_groupMethods = null; 129 130 // Meta groups 131 private Map<String, List<String>> m_metaGroups = Maps.newHashMap(); 132 133 // All the tests that were run along with their result 134 private IResultMap m_passedTests = new ResultMap(); 135 private IResultMap m_failedTests = new ResultMap(); 136 private IResultMap m_failedButWithinSuccessPercentageTests = new ResultMap(); 137 private IResultMap m_skippedTests = new ResultMap(); 138 139 private RunInfo m_runInfo= new RunInfo(); 140 141 // The host where this test was run, or null if run locally 142 private String m_host; 143 144 // Defined dynamically depending on <test preserve-order="true/false"> 145 transient private List<IMethodInterceptor> m_methodInterceptors; 146 147 private transient ClassMethodMap m_classMethodMap; 148 private transient TestNGClassFinder m_testClassFinder; 149 private transient IConfiguration m_configuration; 150 private IMethodInterceptor builtinInterceptor; 151 TestRunner(IConfiguration configuration, ISuite suite, XmlTest test, String outputDirectory, IAnnotationFinder finder, boolean skipFailedInvocationCounts, Collection<IInvokedMethodListener> invokedMethodListeners, List<IClassListener> classListeners)152 protected TestRunner(IConfiguration configuration, 153 ISuite suite, 154 XmlTest test, 155 String outputDirectory, 156 IAnnotationFinder finder, 157 boolean skipFailedInvocationCounts, 158 Collection<IInvokedMethodListener> invokedMethodListeners, 159 List<IClassListener> classListeners) 160 { 161 init(configuration, suite, test, outputDirectory, finder, skipFailedInvocationCounts, 162 invokedMethodListeners, classListeners); 163 } 164 TestRunner(IConfiguration configuration, ISuite suite, XmlTest test, boolean skipFailedInvocationCounts, Collection<IInvokedMethodListener> invokedMethodListeners, List<IClassListener> classListeners)165 public TestRunner(IConfiguration configuration, ISuite suite, XmlTest test, 166 boolean skipFailedInvocationCounts, 167 Collection<IInvokedMethodListener> invokedMethodListeners, 168 List<IClassListener> classListeners) { 169 init(configuration, suite, test, suite.getOutputDirectory(), 170 suite.getAnnotationFinder(), 171 skipFailedInvocationCounts, invokedMethodListeners, classListeners); 172 } 173 init(IConfiguration configuration, ISuite suite, XmlTest test, String outputDirectory, IAnnotationFinder annotationFinder, boolean skipFailedInvocationCounts, Collection<IInvokedMethodListener> invokedMethodListeners, List<IClassListener> classListeners)174 private void init(IConfiguration configuration, 175 ISuite suite, 176 XmlTest test, 177 String outputDirectory, 178 IAnnotationFinder annotationFinder, 179 boolean skipFailedInvocationCounts, 180 Collection<IInvokedMethodListener> invokedMethodListeners, 181 List<IClassListener> classListeners) 182 { 183 m_configuration = configuration; 184 m_xmlTest= test; 185 m_suite = suite; 186 m_testName = test.getName(); 187 m_host = suite.getHost(); 188 m_testClassesFromXml= test.getXmlClasses(); 189 m_skipFailedInvocationCounts = skipFailedInvocationCounts; 190 setVerbose(test.getVerbose()); 191 192 193 boolean preserveOrder = "true".equalsIgnoreCase(test.getPreserveOrder()); 194 m_methodInterceptors = new ArrayList<IMethodInterceptor>(); 195 builtinInterceptor = preserveOrder ? new PreserveOrderMethodInterceptor() : new InstanceOrderingMethodInterceptor(); 196 197 m_packageNamesFromXml= test.getXmlPackages(); 198 if(null != m_packageNamesFromXml) { 199 for(XmlPackage xp: m_packageNamesFromXml) { 200 m_testClassesFromXml.addAll(xp.getXmlClasses()); 201 } 202 } 203 204 m_annotationFinder= annotationFinder; 205 m_invokedMethodListeners = invokedMethodListeners; 206 m_classListeners = classListeners; 207 m_invoker = new Invoker(m_configuration, this, this, m_suite.getSuiteState(), 208 m_skipFailedInvocationCounts, invokedMethodListeners, classListeners); 209 210 if (suite.getParallel() != null) { 211 log(3, "Running the tests in '" + test.getName() + "' with parallel mode:" + suite.getParallel()); 212 } 213 214 setOutputDirectory(outputDirectory); 215 216 // Finish our initialization 217 init(); 218 } 219 getInvoker()220 public IInvoker getInvoker() { 221 return m_invoker; 222 } 223 getBeforeSuiteMethods()224 public ITestNGMethod[] getBeforeSuiteMethods() { 225 return m_beforeSuiteMethods; 226 } 227 getAfterSuiteMethods()228 public ITestNGMethod[] getAfterSuiteMethods() { 229 return m_afterSuiteMethods; 230 } 231 getBeforeTestConfigurationMethods()232 public ITestNGMethod[] getBeforeTestConfigurationMethods() { 233 return m_beforeXmlTestMethods; 234 } 235 getAfterTestConfigurationMethods()236 public ITestNGMethod[] getAfterTestConfigurationMethods() { 237 return m_afterXmlTestMethods; 238 } 239 init()240 private void init() { 241 initMetaGroups(m_xmlTest); 242 initRunInfo(m_xmlTest); 243 244 // Init methods and class map 245 // JUnit behavior is different and doesn't need this initialization step 246 if(!m_xmlTest.isJUnit()) { 247 initMethods(); 248 } 249 250 initListeners(); 251 addConfigurationListener(m_confListener); 252 } 253 254 private static class ListenerHolder { 255 private List<Class<? extends ITestNGListener>> listenerClasses; 256 private Class<? extends ITestNGListenerFactory> listenerFactoryClass; 257 } 258 259 /** 260 * @return all the @Listeners annotations found in the current class and its 261 * superclasses. 262 */ findAllListeners(Class<?> cls)263 private ListenerHolder findAllListeners(Class<?> cls) { 264 ListenerHolder result = new ListenerHolder(); 265 result.listenerClasses = Lists.newArrayList(); 266 267 do { 268 IListenersAnnotation l = m_annotationFinder.findAnnotation(cls, IListenersAnnotation.class); 269 if (l != null) { 270 Class<? extends ITestNGListener>[] classes = l.getValue(); 271 for (Class<? extends ITestNGListener> c : classes) { 272 result.listenerClasses.add(c); 273 274 if (ITestNGListenerFactory.class.isAssignableFrom(c)) { 275 if (result.listenerFactoryClass == null) { 276 result.listenerFactoryClass = (Class<? extends ITestNGListenerFactory>) c; 277 } 278 else { 279 throw new TestNGException("Found more than one class implementing" + 280 "ITestNGListenerFactory:" + c + " and " + result.listenerFactoryClass); 281 } 282 } 283 } 284 } 285 cls = cls.getSuperclass(); 286 } while (cls != Object.class); 287 288 return result; 289 } 290 initListeners()291 private void initListeners() { 292 // 293 // Find all the listener factories and collect all the listeners requested in a 294 // @Listeners annotation. 295 // 296 Set<Class<? extends ITestNGListener>> listenerClasses = Sets.newHashSet(); 297 Class<? extends ITestNGListenerFactory> listenerFactoryClass = null; 298 299 for (IClass cls : getTestClasses()) { 300 Class<? extends ITestNGListenerFactory> realClass = cls.getRealClass(); 301 ListenerHolder listenerHolder = findAllListeners(realClass); 302 if (listenerFactoryClass == null) { 303 listenerFactoryClass = listenerHolder.listenerFactoryClass; 304 } 305 listenerClasses.addAll(listenerHolder.listenerClasses); 306 } 307 308 // 309 // Now we have all the listeners collected from @Listeners and at most one 310 // listener factory collected from a class implementing ITestNGListenerFactory. 311 // Instantiate all the requested listeners. 312 // 313 ITestNGListenerFactory listenerFactory = null; 314 315 // If we found a test listener factory, instantiate it. 316 try { 317 if (m_testClassFinder != null) { 318 IClass ic = m_testClassFinder.getIClass(listenerFactoryClass); 319 if (ic != null) { 320 listenerFactory = (ITestNGListenerFactory) ic.getInstances(false)[0]; 321 } 322 } 323 if (listenerFactory == null) { 324 listenerFactory = listenerFactoryClass != null ? listenerFactoryClass.newInstance() : null; 325 } 326 } 327 catch(Exception ex) { 328 throw new TestNGException("Couldn't instantiate the ITestNGListenerFactory: " 329 + ex); 330 } 331 332 // Instantiate all the listeners 333 for (Class<? extends ITestNGListener> c : listenerClasses) { 334 Object listener = listenerFactory != null ? listenerFactory.createListener(c) : null; 335 if (listener == null) { 336 listener = ClassHelper.newInstance(c); 337 } 338 339 if (listener instanceof IMethodInterceptor) { 340 m_methodInterceptors.add((IMethodInterceptor) listener); 341 } 342 if (listener instanceof ISuiteListener) { 343 m_suite.addListener((ISuiteListener) listener); 344 } 345 if (listener instanceof IInvokedMethodListener) { 346 m_suite.addListener((ITestNGListener) listener); 347 } 348 if (listener instanceof ITestListener) { 349 // At this point, the field m_testListeners has already been used in the creation 350 addTestListener((ITestListener) listener); 351 } 352 if (listener instanceof IClassListener) { 353 m_classListeners.add((IClassListener) listener); 354 } 355 if (listener instanceof IConfigurationListener) { 356 addConfigurationListener((IConfigurationListener) listener); 357 } 358 if (listener instanceof IReporter) { 359 m_suite.addListener((ITestNGListener) listener); 360 } 361 if (listener instanceof IConfigurable) { 362 m_configuration.setConfigurable((IConfigurable) listener); 363 } 364 if (listener instanceof IHookable) { 365 m_configuration.setHookable((IHookable) listener); 366 } 367 if (listener instanceof IExecutionListener) { 368 IExecutionListener iel = (IExecutionListener) listener; 369 iel.onExecutionStart(); 370 m_configuration.addExecutionListener(iel); 371 } 372 } 373 } 374 375 /** 376 * Initialize meta groups 377 */ initMetaGroups(XmlTest xmlTest)378 private void initMetaGroups(XmlTest xmlTest) { 379 Map<String, List<String>> metaGroups = xmlTest.getMetaGroups(); 380 381 for (Map.Entry<String, List<String>> entry : metaGroups.entrySet()) { 382 addMetaGroup(entry.getKey(), entry.getValue()); 383 } 384 } 385 initRunInfo(final XmlTest xmlTest)386 private void initRunInfo(final XmlTest xmlTest) { 387 // Groups 388 m_xmlMethodSelector.setIncludedGroups(createGroups(m_xmlTest.getIncludedGroups())); 389 m_xmlMethodSelector.setExcludedGroups(createGroups(m_xmlTest.getExcludedGroups())); 390 m_xmlMethodSelector.setExpression(m_xmlTest.getExpression()); 391 392 // Methods 393 m_xmlMethodSelector.setXmlClasses(m_xmlTest.getXmlClasses()); 394 395 m_runInfo.addMethodSelector(m_xmlMethodSelector, 10); 396 397 // Add user-specified method selectors (only class selectors, we can ignore 398 // script selectors here) 399 if (null != xmlTest.getMethodSelectors()) { 400 for (org.testng.xml.XmlMethodSelector selector : xmlTest.getMethodSelectors()) { 401 if (selector.getClassName() != null) { 402 IMethodSelector s = ClassHelper.createSelector(selector); 403 404 m_runInfo.addMethodSelector(s, selector.getPriority()); 405 } 406 } 407 } 408 } 409 initMethods()410 private void initMethods() { 411 412 // 413 // Calculate all the methods we need to invoke 414 // 415 List<ITestNGMethod> beforeClassMethods = Lists.newArrayList(); 416 List<ITestNGMethod> testMethods = Lists.newArrayList(); 417 List<ITestNGMethod> afterClassMethods = Lists.newArrayList(); 418 List<ITestNGMethod> beforeSuiteMethods = Lists.newArrayList(); 419 List<ITestNGMethod> afterSuiteMethods = Lists.newArrayList(); 420 List<ITestNGMethod> beforeXmlTestMethods = Lists.newArrayList(); 421 List<ITestNGMethod> afterXmlTestMethods = Lists.newArrayList(); 422 423 ClassInfoMap classMap = new ClassInfoMap(m_testClassesFromXml); 424 m_testClassFinder= new TestNGClassFinder(classMap, 425 null, 426 m_xmlTest, 427 m_configuration, 428 this); 429 ITestMethodFinder testMethodFinder 430 = new TestNGMethodFinder(m_runInfo, m_annotationFinder); 431 432 m_runInfo.setTestMethods(testMethods); 433 434 // 435 // Initialize TestClasses 436 // 437 IClass[] classes = m_testClassFinder.findTestClasses(); 438 439 for (IClass ic : classes) { 440 441 // Create TestClass 442 ITestClass tc = new TestClass(ic, 443 testMethodFinder, 444 m_annotationFinder, 445 m_runInfo, 446 m_xmlTest, 447 classMap.getXmlClass(ic.getRealClass())); 448 m_classMap.put(ic.getRealClass(), tc); 449 } 450 451 // 452 // Calculate groups methods 453 // 454 Map<String, List<ITestNGMethod>> beforeGroupMethods = 455 MethodGroupsHelper.findGroupsMethods(m_classMap.values(), true); 456 Map<String, List<ITestNGMethod>> afterGroupMethods = 457 MethodGroupsHelper.findGroupsMethods(m_classMap.values(), false); 458 459 // 460 // Walk through all the TestClasses, store their method 461 // and initialize them with the correct ITestClass 462 // 463 for (ITestClass tc : m_classMap.values()) { 464 fixMethodsWithClass(tc.getTestMethods(), tc, testMethods); 465 fixMethodsWithClass(tc.getBeforeClassMethods(), tc, beforeClassMethods); 466 fixMethodsWithClass(tc.getBeforeTestMethods(), tc, null); 467 fixMethodsWithClass(tc.getAfterTestMethods(), tc, null); 468 fixMethodsWithClass(tc.getAfterClassMethods(), tc, afterClassMethods); 469 fixMethodsWithClass(tc.getBeforeSuiteMethods(), tc, beforeSuiteMethods); 470 fixMethodsWithClass(tc.getAfterSuiteMethods(), tc, afterSuiteMethods); 471 fixMethodsWithClass(tc.getBeforeTestConfigurationMethods(), tc, beforeXmlTestMethods); 472 fixMethodsWithClass(tc.getAfterTestConfigurationMethods(), tc, afterXmlTestMethods); 473 fixMethodsWithClass(tc.getBeforeGroupsMethods(), tc, 474 MethodHelper.uniqueMethodList(beforeGroupMethods.values())); 475 fixMethodsWithClass(tc.getAfterGroupsMethods(), tc, 476 MethodHelper.uniqueMethodList(afterGroupMethods.values())); 477 } 478 479 // 480 // Sort the methods 481 // 482 m_beforeSuiteMethods = MethodHelper.collectAndOrderMethods(beforeSuiteMethods, 483 false /* forTests */, 484 m_runInfo, 485 m_annotationFinder, 486 true /* unique */, 487 m_excludedMethods); 488 489 m_beforeXmlTestMethods = MethodHelper.collectAndOrderMethods(beforeXmlTestMethods, 490 false /* forTests */, 491 m_runInfo, 492 m_annotationFinder, 493 true /* unique (CQ added by me)*/, 494 m_excludedMethods); 495 496 m_allTestMethods = MethodHelper.collectAndOrderMethods(testMethods, 497 true /* forTest? */, 498 m_runInfo, 499 m_annotationFinder, 500 false /* unique */, 501 m_excludedMethods); 502 m_classMethodMap = new ClassMethodMap(testMethods, m_xmlMethodSelector); 503 504 m_afterXmlTestMethods = MethodHelper.collectAndOrderMethods(afterXmlTestMethods, 505 false /* forTests */, 506 m_runInfo, 507 m_annotationFinder, 508 true /* unique (CQ added by me)*/, 509 m_excludedMethods); 510 511 m_afterSuiteMethods = MethodHelper.collectAndOrderMethods(afterSuiteMethods, 512 false /* forTests */, 513 m_runInfo, 514 m_annotationFinder, 515 true /* unique */, 516 m_excludedMethods); 517 // shared group methods 518 m_groupMethods = new ConfigurationGroupMethods(m_allTestMethods, beforeGroupMethods, afterGroupMethods); 519 520 521 } 522 fixMethodsWithClass(ITestNGMethod[] methods, ITestClass testCls, List<ITestNGMethod> methodList)523 private void fixMethodsWithClass(ITestNGMethod[] methods, 524 ITestClass testCls, 525 List<ITestNGMethod> methodList) { 526 for (ITestNGMethod itm : methods) { 527 itm.setTestClass(testCls); 528 529 if (methodList != null) { 530 methodList.add(itm); 531 } 532 } 533 } 534 getTestClasses()535 public Collection<ITestClass> getTestClasses() { 536 return m_classMap.values(); 537 } 538 setTestName(String name)539 public void setTestName(String name) { 540 m_testName = name; 541 } 542 setOutputDirectory(String od)543 public void setOutputDirectory(String od) { 544 m_outputDirectory= od; 545 // FIX: empty directories were created 546 // if (od == null) { m_outputDirectory = null; return; } //for maven2 547 // File file = new File(od); 548 // file.mkdirs(); 549 // m_outputDirectory= file.getAbsolutePath(); 550 } 551 addMetaGroup(String name, List<String> groupNames)552 private void addMetaGroup(String name, List<String> groupNames) { 553 m_metaGroups.put(name, groupNames); 554 } 555 556 /** 557 * Calculate the transitive closure of all the MetaGroups 558 * 559 * @param groups 560 * @param unfinishedGroups 561 * @param result The transitive closure containing all the groups found 562 */ collectGroups(String[] groups, List<String> unfinishedGroups, Map<String, String> result)563 private void collectGroups(String[] groups, 564 List<String> unfinishedGroups, 565 Map<String, String> result) { 566 for (String gn : groups) { 567 List<String> subGroups = m_metaGroups.get(gn); 568 if (null != subGroups) { 569 570 for (String sg : subGroups) { 571 if (null == result.get(sg)) { 572 result.put(sg, sg); 573 unfinishedGroups.add(sg); 574 } 575 } 576 } 577 } 578 } 579 createGroups(List<String> groups)580 private Map<String, String> createGroups(List<String> groups) { 581 return createGroups(groups.toArray(new String[groups.size()])); 582 } 583 createGroups(String[] groups)584 private Map<String, String> createGroups(String[] groups) { 585 Map<String, String> result = Maps.newHashMap(); 586 587 // Groups that were passed on the command line 588 for (String group : groups) { 589 result.put(group, group); 590 } 591 592 // See if we have any MetaGroups and 593 // expand them if they match one of the groups 594 // we have just been passed 595 List<String> unfinishedGroups = Lists.newArrayList(); 596 597 if (m_metaGroups.size() > 0) { 598 collectGroups(groups, unfinishedGroups, result); 599 600 // Do we need to loop over unfinished groups? 601 while (unfinishedGroups.size() > 0) { 602 String[] uGroups = unfinishedGroups.toArray(new String[unfinishedGroups.size()]); 603 unfinishedGroups = Lists.newArrayList(); 604 collectGroups(uGroups, unfinishedGroups, result); 605 } 606 } 607 608 // Utils.dumpMap(result); 609 return result; 610 } 611 612 /** 613 * The main entry method for TestRunner. 614 * 615 * This is where all the hard work is done: 616 * - Invoke configuration methods 617 * - Invoke test methods 618 * - Catch exceptions 619 * - Collect results 620 * - Invoke listeners 621 * - etc... 622 */ run()623 public void run() { 624 beforeRun(); 625 626 try { 627 XmlTest test= getTest(); 628 if(test.isJUnit()) { 629 privateRunJUnit(test); 630 } 631 else { 632 privateRun(test); 633 } 634 } 635 finally { 636 afterRun(); 637 } 638 } 639 640 /** Before run preparements. */ beforeRun()641 private void beforeRun() { 642 // 643 // Log the start date 644 // 645 m_startDate = new Date(System.currentTimeMillis()); 646 647 // Log start 648 logStart(); 649 650 // Invoke listeners 651 fireEvent(true /*start*/); 652 653 // invoke @BeforeTest 654 ITestNGMethod[] testConfigurationMethods= getBeforeTestConfigurationMethods(); 655 if(null != testConfigurationMethods && testConfigurationMethods.length > 0) { 656 m_invoker.invokeConfigurations(null, 657 testConfigurationMethods, 658 m_xmlTest.getSuite(), 659 m_xmlTest.getAllParameters(), 660 null, /* no parameter values */ 661 null /* instance */); 662 } 663 } 664 privateRunJUnit(XmlTest xmlTest)665 private void privateRunJUnit(XmlTest xmlTest) { 666 final ClassInfoMap cim = new ClassInfoMap(m_testClassesFromXml, false); 667 final Set<Class<?>> classes = cim.getClasses(); 668 final List<ITestNGMethod> runMethods = Lists.newArrayList(); 669 List<IWorker<ITestNGMethod>> workers = Lists.newArrayList(); 670 // FIXME: directly referencing JUnitTestRunner which uses JUnit classes 671 // may result in an class resolution exception under different JVMs 672 // The resolution process is not specified in the JVM spec with a specific implementation, 673 // so it can be eager => failure 674 workers.add(new IWorker<ITestNGMethod>() { 675 /** 676 * @see TestMethodWorker#getTimeOut() 677 */ 678 @Override 679 public long getTimeOut() { 680 return 0; 681 } 682 683 /** 684 * @see java.lang.Runnable#run() 685 */ 686 @Override 687 public void run() { 688 for(Class<?> tc: classes) { 689 List<XmlInclude> includedMethods = cim.getXmlClass(tc).getIncludedMethods(); 690 List<String> methods = Lists.newArrayList(); 691 for (XmlInclude inc: includedMethods) { 692 methods.add(inc.getName()); 693 } 694 IJUnitTestRunner tr= ClassHelper.createTestRunner(TestRunner.this); 695 tr.setInvokedMethodListeners(m_invokedMethodListeners); 696 try { 697 tr.run(tc, methods.toArray(new String[methods.size()])); 698 } 699 catch(Exception ex) { 700 ex.printStackTrace(); 701 } 702 finally { 703 runMethods.addAll(tr.getTestMethods()); 704 } 705 } 706 } 707 708 @Override 709 public List<ITestNGMethod> getTasks() { 710 throw new TestNGException("JUnit not supported"); 711 } 712 713 @Override 714 public int getPriority() { 715 if (m_allTestMethods.length == 1) { 716 return m_allTestMethods[0].getPriority(); 717 } else { 718 return 0; 719 } 720 } 721 722 @Override 723 public int compareTo(IWorker<ITestNGMethod> other) { 724 return getPriority() - other.getPriority(); 725 } 726 }); 727 728 runJUnitWorkers(workers); 729 m_allTestMethods= runMethods.toArray(new ITestNGMethod[runMethods.size()]); 730 } 731 732 private static final EnumSet<XmlSuite.ParallelMode> PRIVATE_RUN_PARALLEL_MODES 733 = EnumSet.of(XmlSuite.ParallelMode.METHODS, XmlSuite.ParallelMode.TRUE, 734 XmlSuite.ParallelMode.CLASSES, XmlSuite.ParallelMode.INSTANCES); 735 /** 736 * Main method that create a graph of methods and then pass it to the 737 * graph executor to run them. 738 */ privateRun(XmlTest xmlTest)739 private void privateRun(XmlTest xmlTest) { 740 XmlSuite.ParallelMode parallelMode = xmlTest.getParallel(); 741 boolean parallel = PRIVATE_RUN_PARALLEL_MODES.contains(parallelMode); 742 743 { 744 // parallel 745 int threadCount = parallel ? xmlTest.getThreadCount() : 1; 746 // Make sure we create a graph based on the intercepted methods, otherwise an interceptor 747 // removing methods would cause the graph never to terminate (because it would expect 748 // termination from methods that never get invoked). 749 DynamicGraph<ITestNGMethod> graph = createDynamicGraph(intercept(m_allTestMethods)); 750 if (parallel) { 751 if (graph.getNodeCount() > 0) { 752 GraphThreadPoolExecutor<ITestNGMethod> executor = 753 new GraphThreadPoolExecutor<>(graph, this, 754 threadCount, threadCount, 0, TimeUnit.MILLISECONDS, 755 new LinkedBlockingQueue<Runnable>()); 756 executor.run(); 757 try { 758 long timeOut = m_xmlTest.getTimeOut(XmlTest.DEFAULT_TIMEOUT_MS); 759 Utils.log("TestRunner", 2, "Starting executor for test " + m_xmlTest.getName() 760 + " with time out:" + timeOut + " milliseconds."); 761 executor.awaitTermination(timeOut, TimeUnit.MILLISECONDS); 762 executor.shutdownNow(); 763 } catch (InterruptedException handled) { 764 handled.printStackTrace(); 765 Thread.currentThread().interrupt(); 766 } 767 } 768 } else { 769 boolean debug = false; 770 List<ITestNGMethod> freeNodes = graph.getFreeNodes(); 771 if (debug) { 772 System.out.println("Free nodes:" + freeNodes); 773 } 774 775 if (graph.getNodeCount() > 0 && freeNodes.isEmpty()) { 776 throw new TestNGException("No free nodes found in:" + graph); 777 } 778 779 while (! freeNodes.isEmpty()) { 780 List<IWorker<ITestNGMethod>> runnables = createWorkers(freeNodes); 781 for (IWorker<ITestNGMethod> r : runnables) { 782 r.run(); 783 } 784 graph.setStatus(freeNodes, Status.FINISHED); 785 freeNodes = graph.getFreeNodes(); 786 if (debug) { 787 System.out.println("Free nodes:" + freeNodes); 788 } 789 } 790 } 791 } 792 } 793 794 /** 795 * Apply the method interceptor (if applicable) to the list of methods. 796 */ intercept(ITestNGMethod[] methods)797 private ITestNGMethod[] intercept(ITestNGMethod[] methods) { 798 List<IMethodInstance> methodInstances = methodsToMethodInstances(Arrays.asList(methods)); 799 800 // add built-in interceptor (PreserveOrderMethodInterceptor or InstanceOrderingMethodInterceptor at the end of the list 801 m_methodInterceptors.add(builtinInterceptor); 802 for (IMethodInterceptor m_methodInterceptor : m_methodInterceptors) { 803 methodInstances = m_methodInterceptor.intercept(methodInstances, this); 804 } 805 806 List<ITestNGMethod> result = Lists.newArrayList(); 807 for (IMethodInstance imi : methodInstances) { 808 result.add(imi.getMethod()); 809 } 810 811 //Since an interceptor is involved, we would need to ensure that the ClassMethodMap object is in sync with the 812 //output of the interceptor, else @AfterClass doesn't get executed at all when interceptors are involved. 813 //so let's update the current classMethodMap object with the list of methods obtained from the interceptor. 814 this.m_classMethodMap = new ClassMethodMap(result, null); 815 816 return result.toArray(new ITestNGMethod[result.size()]); 817 } 818 819 /** 820 * Create a list of workers to run the methods passed in parameter. 821 * Each test method is run in its own worker except in the following cases: 822 * - The method belongs to a class that has @Test(sequential=true) 823 * - The parallel attribute is set to "classes" 824 * In both these cases, all the methods belonging to that class will then 825 * be put in the same worker in order to run in the same thread. 826 */ 827 @Override createWorkers(List<ITestNGMethod> methods)828 public List<IWorker<ITestNGMethod>> createWorkers(List<ITestNGMethod> methods) { 829 List<IWorker<ITestNGMethod>> result; 830 if (XmlSuite.ParallelMode.INSTANCES.equals(m_xmlTest.getParallel())) { 831 result = createInstanceBasedParallelWorkers(methods); 832 } else { 833 result = createClassBasedParallelWorkers(methods); 834 } 835 return result; 836 } 837 838 /** 839 * Create workers for parallel="classes" and similar cases. 840 */ createClassBasedParallelWorkers(List<ITestNGMethod> methods)841 private List<IWorker<ITestNGMethod>> createClassBasedParallelWorkers(List<ITestNGMethod> methods) { 842 List<IWorker<ITestNGMethod>> result = Lists.newArrayList(); 843 // Methods that belong to classes with a sequential=true or parallel=classes 844 // attribute must all be run in the same worker 845 Set<Class> sequentialClasses = Sets.newHashSet(); 846 for (ITestNGMethod m : methods) { 847 Class<? extends ITestClass> cls = m.getRealClass(); 848 org.testng.annotations.ITestAnnotation test = 849 m_annotationFinder.findAnnotation(cls, org.testng.annotations.ITestAnnotation.class); 850 851 // If either sequential=true or parallel=classes, mark this class sequential 852 if (test != null && (test.getSequential() || test.getSingleThreaded()) || 853 XmlSuite.ParallelMode.CLASSES.equals(m_xmlTest.getParallel())) { 854 sequentialClasses.add(cls); 855 } 856 } 857 858 List<IMethodInstance> methodInstances = Lists.newArrayList(); 859 for (ITestNGMethod tm : methods) { 860 methodInstances.addAll(methodsToMultipleMethodInstances(tm)); 861 } 862 863 864 Map<String, String> params = m_xmlTest.getAllParameters(); 865 866 Set<Class<?>> processedClasses = Sets.newHashSet(); 867 for (IMethodInstance im : methodInstances) { 868 Class<?> c = im.getMethod().getTestClass().getRealClass(); 869 if (sequentialClasses.contains(c)) { 870 if (!processedClasses.contains(c)) { 871 processedClasses.add(c); 872 if (System.getProperty("experimental") != null) { 873 List<List<IMethodInstance>> instances = createInstances(methodInstances); 874 for (List<IMethodInstance> inst : instances) { 875 TestMethodWorker worker = createTestMethodWorker(inst, params, c); 876 result.add(worker); 877 } 878 } 879 else { 880 // Sequential class: all methods in one worker 881 TestMethodWorker worker = createTestMethodWorker(methodInstances, params, c); 882 result.add(worker); 883 } 884 } 885 } 886 else { 887 // Parallel class: each method in its own worker 888 TestMethodWorker worker = createTestMethodWorker(Arrays.asList(im), params, c); 889 result.add(worker); 890 } 891 } 892 893 // Sort by priorities 894 Collections.sort(result); 895 return result; 896 } 897 898 899 /** 900 * Create workers for parallel="instances". 901 */ 902 private List<IWorker<ITestNGMethod>> createInstanceBasedParallelWorkers(List<ITestNGMethod> methods)903 createInstanceBasedParallelWorkers(List<ITestNGMethod> methods) { 904 List<IWorker<ITestNGMethod>> result = Lists.newArrayList(); 905 ListMultiMap<Object, ITestNGMethod> lmm = Maps.newListMultiMap(); 906 for (ITestNGMethod m : methods) { 907 lmm.put(m.getInstance(), m); 908 } 909 for (Map.Entry<Object, List<ITestNGMethod>> es : lmm.entrySet()) { 910 List<IMethodInstance> methodInstances = Lists.newArrayList(); 911 for (ITestNGMethod m : es.getValue()) { 912 methodInstances.add(new MethodInstance(m)); 913 } 914 TestMethodWorker tmw = new TestMethodWorker(m_invoker, 915 methodInstances.toArray(new IMethodInstance[methodInstances.size()]), 916 m_xmlTest.getSuite(), 917 m_xmlTest.getAllParameters(), 918 m_groupMethods, 919 m_classMethodMap, 920 this, 921 m_classListeners); 922 result.add(tmw); 923 } 924 925 return result; 926 } 927 createInstances(List<IMethodInstance> methodInstances)928 private List<List<IMethodInstance>> createInstances(List<IMethodInstance> methodInstances) { 929 Map<Object, List<IMethodInstance>> map = Maps.newHashMap(); 930 // MapList<IMethodInstance[], Object> map = new MapList<IMethodInstance[], Object>(); 931 for (IMethodInstance imi : methodInstances) { 932 for (Object o : imi.getInstances()) { 933 System.out.println(o); 934 List<IMethodInstance> l = map.get(o); 935 if (l == null) { 936 l = Lists.newArrayList(); 937 map.put(o, l); 938 } 939 l.add(imi); 940 } 941 // for (Object instance : imi.getInstances()) { 942 // map.put(imi, instance); 943 // } 944 } 945 // return map.getKeys(); 946 // System.out.println(map); 947 return new ArrayList<>(map.values()); 948 } 949 createTestMethodWorker( List<IMethodInstance> methodInstances, Map<String, String> params, Class<?> c)950 private TestMethodWorker createTestMethodWorker( 951 List<IMethodInstance> methodInstances, Map<String, String> params, 952 Class<?> c) { 953 return new TestMethodWorker(m_invoker, 954 findClasses(methodInstances, c), 955 m_xmlTest.getSuite(), 956 params, 957 m_groupMethods, 958 m_classMethodMap, 959 this, 960 m_classListeners); 961 } 962 findClasses(List<IMethodInstance> methodInstances, Class<?> c)963 private IMethodInstance[] findClasses(List<IMethodInstance> methodInstances, Class<?> c) { 964 List<IMethodInstance> result = Lists.newArrayList(); 965 for (IMethodInstance mi : methodInstances) { 966 if (mi.getMethod().getTestClass().getRealClass() == c) { 967 result.add(mi); 968 } 969 } 970 return result.toArray(new IMethodInstance[result.size()]); 971 } 972 973 /** 974 * @@@ remove this 975 */ methodsToMultipleMethodInstances(ITestNGMethod... sl)976 private List<MethodInstance> methodsToMultipleMethodInstances(ITestNGMethod... sl) { 977 List<MethodInstance> vResult = Lists.newArrayList(); 978 for (ITestNGMethod m : sl) { 979 vResult.add(new MethodInstance(m)); 980 } 981 982 return vResult; 983 } 984 methodsToMethodInstances(List<ITestNGMethod> sl)985 private List<IMethodInstance> methodsToMethodInstances(List<ITestNGMethod> sl) { 986 List<IMethodInstance> result = new ArrayList<>(); 987 for (ITestNGMethod iTestNGMethod : sl) { 988 result.add(new MethodInstance(iTestNGMethod)); 989 } 990 return result; 991 } 992 993 // 994 // Invoke the workers 995 // 996 private static final EnumSet<XmlSuite.ParallelMode> WORKERS_PARALLEL_MODES 997 = EnumSet.of(XmlSuite.ParallelMode.METHODS, XmlSuite.ParallelMode.TRUE, 998 XmlSuite.ParallelMode.CLASSES); runJUnitWorkers(List<? extends IWorker<ITestNGMethod>> workers)999 private void runJUnitWorkers(List<? extends IWorker<ITestNGMethod>> workers) { 1000 // 1001 // Sequential run 1002 // 1003 for (IWorker<ITestNGMethod> tmw : workers) { 1004 tmw.run(); 1005 } 1006 } 1007 afterRun()1008 private void afterRun() { 1009 // invoke @AfterTest 1010 ITestNGMethod[] testConfigurationMethods= getAfterTestConfigurationMethods(); 1011 if(null != testConfigurationMethods && testConfigurationMethods.length > 0) { 1012 m_invoker.invokeConfigurations(null, 1013 testConfigurationMethods, 1014 m_xmlTest.getSuite(), 1015 m_xmlTest.getAllParameters(), 1016 null, /* no parameter values */ 1017 null /* instance */); 1018 } 1019 1020 // 1021 // Log the end date 1022 // 1023 m_endDate = new Date(System.currentTimeMillis()); 1024 1025 if (getVerbose() >= 3) { 1026 dumpInvokedMethods(); 1027 } 1028 1029 // Invoke listeners 1030 fireEvent(false /*stop*/); 1031 1032 // Statistics 1033 // logResults(); 1034 } 1035 createDynamicGraph(ITestNGMethod[] methods)1036 private DynamicGraph<ITestNGMethod> createDynamicGraph(ITestNGMethod[] methods) { 1037 DynamicGraph<ITestNGMethod> result = new DynamicGraph<>(); 1038 result.setComparator(new Comparator<ITestNGMethod>() { 1039 @Override 1040 public int compare(ITestNGMethod o1, ITestNGMethod o2) { 1041 return o1.getPriority() - o2.getPriority(); 1042 } 1043 }); 1044 1045 DependencyMap dependencyMap = new DependencyMap(methods); 1046 1047 // Keep track of whether we have group dependencies. If we do, preserve-order needs 1048 // to be ignored since group dependencies create inter-class dependencies which can 1049 // end up creating cycles when combined with preserve-order. 1050 boolean hasDependencies = false; 1051 for (ITestNGMethod m : methods) { 1052 result.addNode(m); 1053 1054 // Dependent methods 1055 { 1056 String[] dependentMethods = m.getMethodsDependedUpon(); 1057 if (dependentMethods != null) { 1058 for (String d : dependentMethods) { 1059 ITestNGMethod dm = dependencyMap.getMethodDependingOn(d, m); 1060 if (m != dm){ 1061 result.addEdge(m, dm); 1062 } 1063 } 1064 } 1065 } 1066 1067 // Dependent groups 1068 { 1069 String[] dependentGroups = m.getGroupsDependedUpon(); 1070 for (String d : dependentGroups) { 1071 hasDependencies = true; 1072 List<ITestNGMethod> dg = dependencyMap.getMethodsThatBelongTo(d, m); 1073 if (dg == null) { 1074 throw new TestNGException("Method \"" + m 1075 + "\" depends on nonexistent group \"" + d + "\""); 1076 } 1077 for (ITestNGMethod ddm : dg) { 1078 result.addEdge(m, ddm); 1079 } 1080 } 1081 } 1082 } 1083 1084 // Preserve order 1085 // Don't preserve the ordering if we're running in parallel, otherwise the suite will 1086 // create multiple threads but these threads will be created one after the other, 1087 // giving the impression of parallelism (multiple thread id's) while still running 1088 // sequentially. 1089 if (! hasDependencies 1090 && getCurrentXmlTest().getParallel() == XmlSuite.ParallelMode.FALSE 1091 && "true".equalsIgnoreCase(getCurrentXmlTest().getPreserveOrder())) { 1092 // If preserve-order was specified and the class order is A, B 1093 // create a new set of dependencies where each method of B depends 1094 // on all the methods of A 1095 ListMultiMap<ITestNGMethod, ITestNGMethod> classDependencies 1096 = createClassDependencies(methods, getCurrentXmlTest()); 1097 1098 for (Map.Entry<ITestNGMethod, List<ITestNGMethod>> es : classDependencies.entrySet()) { 1099 for (ITestNGMethod dm : es.getValue()) { 1100 result.addEdge(dm, es.getKey()); 1101 } 1102 } 1103 } 1104 1105 // Group by instances 1106 if (getCurrentXmlTest().getGroupByInstances()) { 1107 ListMultiMap<ITestNGMethod, ITestNGMethod> instanceDependencies 1108 = createInstanceDependencies(methods, getCurrentXmlTest()); 1109 1110 for (Map.Entry<ITestNGMethod, List<ITestNGMethod>> es : instanceDependencies.entrySet()) { 1111 for (ITestNGMethod dm : es.getValue()) { 1112 result.addEdge(dm, es.getKey()); 1113 } 1114 } 1115 1116 } 1117 1118 return result; 1119 } 1120 createInstanceDependencies( ITestNGMethod[] methods, XmlTest currentXmlTest)1121 private ListMultiMap<ITestNGMethod, ITestNGMethod> createInstanceDependencies( 1122 ITestNGMethod[] methods, XmlTest currentXmlTest) 1123 { 1124 ListMultiMap<Object, ITestNGMethod> instanceMap = Maps.newListMultiMap(); 1125 for (ITestNGMethod m : methods) { 1126 instanceMap.put(m.getInstance(), m); 1127 } 1128 1129 ListMultiMap<ITestNGMethod, ITestNGMethod> result = Maps.newListMultiMap(); 1130 Object previousInstance = null; 1131 for (Map.Entry<Object, List<ITestNGMethod>> es : instanceMap.entrySet()) { 1132 if (previousInstance == null) { 1133 previousInstance = es.getKey(); 1134 } else { 1135 List<ITestNGMethod> previousMethods = instanceMap.get(previousInstance); 1136 Object currentInstance = es.getKey(); 1137 List<ITestNGMethod> currentMethods = instanceMap.get(currentInstance); 1138 // Make all the methods from the current instance depend on the methods of 1139 // the previous instance 1140 for (ITestNGMethod cm : currentMethods) { 1141 for (ITestNGMethod pm : previousMethods) { 1142 result.put(cm, pm); 1143 } 1144 } 1145 previousInstance = currentInstance; 1146 } 1147 } 1148 1149 return result; 1150 } 1151 createClassDependencies( ITestNGMethod[] methods, XmlTest test)1152 private ListMultiMap<ITestNGMethod, ITestNGMethod> createClassDependencies( 1153 ITestNGMethod[] methods, XmlTest test) 1154 { 1155 Map<String, List<ITestNGMethod>> classes = Maps.newHashMap(); 1156 // Note: use a List here to preserve the ordering but make sure 1157 // we don't add the same class twice 1158 List<XmlClass> sortedClasses = Lists.newArrayList(); 1159 1160 for (XmlClass c : test.getXmlClasses()) { 1161 classes.put(c.getName(), new ArrayList<ITestNGMethod>()); 1162 if (! sortedClasses.contains(c)) sortedClasses.add(c); 1163 } 1164 1165 // Sort the classes based on their order of appearance in the XML 1166 Collections.sort(sortedClasses, new Comparator<XmlClass>() { 1167 @Override 1168 public int compare(XmlClass arg0, XmlClass arg1) { 1169 return arg0.getIndex() - arg1.getIndex(); 1170 } 1171 }); 1172 1173 Map<String, Integer> indexedClasses1 = Maps.newHashMap(); 1174 Map<Integer, String> indexedClasses2 = Maps.newHashMap(); 1175 int i = 0; 1176 for (XmlClass c : sortedClasses) { 1177 indexedClasses1.put(c.getName(), i); 1178 indexedClasses2.put(i, c.getName()); 1179 i++; 1180 } 1181 1182 ListMultiMap<String, ITestNGMethod> methodsFromClass = Maps.newListMultiMap(); 1183 for (ITestNGMethod m : methods) { 1184 methodsFromClass.put(m.getTestClass().getName(), m); 1185 } 1186 1187 ListMultiMap<ITestNGMethod, ITestNGMethod> result = Maps.newListMultiMap(); 1188 for (ITestNGMethod m : methods) { 1189 String name = m.getTestClass().getName(); 1190 Integer index = indexedClasses1.get(name); 1191 // The index could be null if the classes listed in the XML are different 1192 // from the methods being run (e.g. the .xml only contains a factory that 1193 // instantiates methods from a different class). In this case, we cannot 1194 // perform any ordering. 1195 if (index != null && index > 0) { 1196 // Make this method depend on all the methods of the class in the previous 1197 // index 1198 String classDependedUpon = indexedClasses2.get(index - 1); 1199 List<ITestNGMethod> methodsDependedUpon = methodsFromClass.get(classDependedUpon); 1200 if (methodsDependedUpon != null) { 1201 for (ITestNGMethod mdu : methodsDependedUpon) { 1202 result.put(mdu, m); 1203 } 1204 } 1205 } 1206 } 1207 1208 return result; 1209 } 1210 1211 /** 1212 * Logs the beginning of the {@link #beforeRun()} . 1213 */ logStart()1214 private void logStart() { 1215 log(3, 1216 "Running test " + m_testName + " on " + m_classMap.size() + " " + " classes, " 1217 + " included groups:[" + mapToString(m_xmlMethodSelector.getIncludedGroups()) 1218 + "] excluded groups:[" + mapToString(m_xmlMethodSelector.getExcludedGroups()) + "]"); 1219 1220 if (getVerbose() >= 3) { 1221 for (ITestClass tc : m_classMap.values()) { 1222 ((TestClass) tc).dump(); 1223 } 1224 } 1225 } 1226 1227 /** 1228 * Trigger the start/finish event. 1229 * 1230 * @param isStart <tt>true</tt> if the event is for start, <tt>false</tt> if the 1231 * event is for finish 1232 */ fireEvent(boolean isStart)1233 private void fireEvent(boolean isStart) { 1234 for (ITestListener itl : m_testListeners) { 1235 if (isStart) { 1236 itl.onStart(this); 1237 } 1238 else { 1239 itl.onFinish(this); 1240 } 1241 } 1242 } 1243 1244 ///// 1245 // ITestContext 1246 // 1247 @Override getName()1248 public String getName() { 1249 return m_testName; 1250 } 1251 1252 /** 1253 * @return Returns the startDate. 1254 */ 1255 @Override getStartDate()1256 public Date getStartDate() { 1257 return m_startDate; 1258 } 1259 1260 /** 1261 * @return Returns the endDate. 1262 */ 1263 @Override getEndDate()1264 public Date getEndDate() { 1265 return m_endDate; 1266 } 1267 1268 @Override getPassedTests()1269 public IResultMap getPassedTests() { 1270 return m_passedTests; 1271 } 1272 1273 @Override getSkippedTests()1274 public IResultMap getSkippedTests() { 1275 return m_skippedTests; 1276 } 1277 1278 @Override getFailedTests()1279 public IResultMap getFailedTests() { 1280 return m_failedTests; 1281 } 1282 1283 @Override getFailedButWithinSuccessPercentageTests()1284 public IResultMap getFailedButWithinSuccessPercentageTests() { 1285 return m_failedButWithinSuccessPercentageTests; 1286 } 1287 1288 @Override getIncludedGroups()1289 public String[] getIncludedGroups() { 1290 Map<String, String> ig= m_xmlMethodSelector.getIncludedGroups(); 1291 String[] result= ig.values().toArray((new String[ig.size()])); 1292 1293 return result; 1294 } 1295 1296 @Override getExcludedGroups()1297 public String[] getExcludedGroups() { 1298 Map<String, String> eg= m_xmlMethodSelector.getExcludedGroups(); 1299 String[] result= eg.values().toArray((new String[eg.size()])); 1300 1301 return result; 1302 } 1303 1304 @Override getOutputDirectory()1305 public String getOutputDirectory() { 1306 return m_outputDirectory; 1307 } 1308 1309 /** 1310 * @return Returns the suite. 1311 */ 1312 @Override getSuite()1313 public ISuite getSuite() { 1314 return m_suite; 1315 } 1316 1317 @Override getAllTestMethods()1318 public ITestNGMethod[] getAllTestMethods() { 1319 return m_allTestMethods; 1320 } 1321 1322 1323 @Override getHost()1324 public String getHost() { 1325 return m_host; 1326 } 1327 1328 @Override getExcludedMethods()1329 public Collection<ITestNGMethod> getExcludedMethods() { 1330 Map<ITestNGMethod, ITestNGMethod> vResult = Maps.newHashMap(); 1331 1332 for (ITestNGMethod m : m_excludedMethods) { 1333 vResult.put(m, m); 1334 } 1335 1336 return vResult.keySet(); 1337 } 1338 1339 /** 1340 * @see org.testng.ITestContext#getFailedConfigurations() 1341 */ 1342 @Override getFailedConfigurations()1343 public IResultMap getFailedConfigurations() { 1344 return m_failedConfigurations; 1345 } 1346 1347 /** 1348 * @see org.testng.ITestContext#getPassedConfigurations() 1349 */ 1350 @Override getPassedConfigurations()1351 public IResultMap getPassedConfigurations() { 1352 return m_passedConfigurations; 1353 } 1354 1355 /** 1356 * @see org.testng.ITestContext#getSkippedConfigurations() 1357 */ 1358 @Override getSkippedConfigurations()1359 public IResultMap getSkippedConfigurations() { 1360 return m_skippedConfigurations; 1361 } 1362 1363 // 1364 // ITestContext 1365 ///// 1366 1367 ///// 1368 // ITestResultNotifier 1369 // 1370 1371 @Override addPassedTest(ITestNGMethod tm, ITestResult tr)1372 public void addPassedTest(ITestNGMethod tm, ITestResult tr) { 1373 m_passedTests.addResult(tr, tm); 1374 } 1375 1376 @Override getPassedTests(ITestNGMethod tm)1377 public Set<ITestResult> getPassedTests(ITestNGMethod tm) { 1378 return m_passedTests.getResults(tm); 1379 } 1380 1381 @Override getFailedTests(ITestNGMethod tm)1382 public Set<ITestResult> getFailedTests(ITestNGMethod tm) { 1383 return m_failedTests.getResults(tm); 1384 } 1385 1386 @Override getSkippedTests(ITestNGMethod tm)1387 public Set<ITestResult> getSkippedTests(ITestNGMethod tm) { 1388 return m_skippedTests.getResults(tm); 1389 } 1390 1391 @Override addSkippedTest(ITestNGMethod tm, ITestResult tr)1392 public void addSkippedTest(ITestNGMethod tm, ITestResult tr) { 1393 m_skippedTests.addResult(tr, tm); 1394 } 1395 1396 @Override addInvokedMethod(InvokedMethod im)1397 public void addInvokedMethod(InvokedMethod im) { 1398 synchronized(m_invokedMethods) { 1399 m_invokedMethods.add(im); 1400 } 1401 } 1402 1403 @Override addFailedTest(ITestNGMethod testMethod, ITestResult result)1404 public void addFailedTest(ITestNGMethod testMethod, ITestResult result) { 1405 logFailedTest(testMethod, result, false /* withinSuccessPercentage */); 1406 } 1407 1408 @Override addFailedButWithinSuccessPercentageTest(ITestNGMethod testMethod, ITestResult result)1409 public void addFailedButWithinSuccessPercentageTest(ITestNGMethod testMethod, 1410 ITestResult result) { 1411 logFailedTest(testMethod, result, true /* withinSuccessPercentage */); 1412 } 1413 1414 @Override getTest()1415 public XmlTest getTest() { 1416 return m_xmlTest; 1417 } 1418 1419 @Override getTestListeners()1420 public List<ITestListener> getTestListeners() { 1421 return m_testListeners; 1422 } 1423 1424 @Override getConfigurationListeners()1425 public List<IConfigurationListener> getConfigurationListeners() { 1426 return Lists.<IConfigurationListener>newArrayList(m_configurationListeners); 1427 } 1428 // 1429 // ITestResultNotifier 1430 ///// 1431 logFailedTest(ITestNGMethod method, ITestResult tr, boolean withinSuccessPercentage)1432 private void logFailedTest(ITestNGMethod method, 1433 ITestResult tr, 1434 boolean withinSuccessPercentage) { 1435 /* 1436 * We should not remove a passed method from m_passedTests so that we can 1437 * account for the passed instances of this test method. 1438 */ 1439 //m_passedTests.removeResult(method); 1440 if (withinSuccessPercentage) { 1441 m_failedButWithinSuccessPercentageTests.addResult(tr, method); 1442 } 1443 else { 1444 m_failedTests.addResult(tr, method); 1445 } 1446 } 1447 mapToString(Map<?, ?> m)1448 private String mapToString(Map<?, ?> m) { 1449 StringBuffer result= new StringBuffer(); 1450 for (Object o : m.values()) { 1451 result.append(o.toString()).append(" "); 1452 } 1453 1454 return result.toString(); 1455 } 1456 log(int level, String s)1457 private void log(int level, String s) { 1458 Utils.log("TestRunner", level, s); 1459 } 1460 getVerbose()1461 public static int getVerbose() { 1462 return m_verbose; 1463 } 1464 setVerbose(int n)1465 public void setVerbose(int n) { 1466 m_verbose = n; 1467 } 1468 log(String s)1469 private void log(String s) { 1470 Utils.log("TestRunner", 2, s); 1471 } 1472 1473 ///// 1474 // Listeners 1475 // addListener(Object listener)1476 public void addListener(Object listener) { 1477 if(listener instanceof ITestListener) { 1478 addTestListener((ITestListener) listener); 1479 } 1480 if(listener instanceof IConfigurationListener) { 1481 addConfigurationListener((IConfigurationListener) listener); 1482 } 1483 if(listener instanceof IClassListener) { 1484 addClassListener((IClassListener) listener); 1485 } 1486 } 1487 addTestListener(ITestListener il)1488 public void addTestListener(ITestListener il) { 1489 m_testListeners.add(il); 1490 } 1491 addClassListener(IClassListener cl)1492 public void addClassListener(IClassListener cl) { 1493 m_classListeners.add(cl); 1494 } 1495 addConfigurationListener(IConfigurationListener icl)1496 void addConfigurationListener(IConfigurationListener icl) { 1497 m_configurationListeners.add(icl); 1498 } 1499 // 1500 // Listeners 1501 ///// 1502 1503 private final List<InvokedMethod> m_invokedMethods = Lists.newArrayList(); 1504 dumpInvokedMethods()1505 private void dumpInvokedMethods() { 1506 System.out.println("===== Invoked methods"); 1507 for (IInvokedMethod im : m_invokedMethods) { 1508 if (im.isTestMethod()) { 1509 System.out.print(" "); 1510 } 1511 else if (im.isConfigurationMethod()) { 1512 System.out.print(" "); 1513 } 1514 else { 1515 continue; 1516 } 1517 System.out.println("" + im); 1518 } 1519 System.out.println("====="); 1520 } 1521 getInvokedMethods()1522 public List<ITestNGMethod> getInvokedMethods() { 1523 List<ITestNGMethod> result= Lists.newArrayList(); 1524 synchronized(m_invokedMethods) { 1525 for (IInvokedMethod im : m_invokedMethods) { 1526 ITestNGMethod tm= im.getTestMethod(); 1527 tm.setDate(im.getDate()); 1528 result.add(tm); 1529 } 1530 } 1531 1532 return result; 1533 } 1534 1535 private IResultMap m_passedConfigurations= new ResultMap(); 1536 private IResultMap m_skippedConfigurations= new ResultMap(); 1537 private IResultMap m_failedConfigurations= new ResultMap(); 1538 1539 private class ConfigurationListener implements IConfigurationListener2 { 1540 @Override beforeConfiguration(ITestResult tr)1541 public void beforeConfiguration(ITestResult tr) { 1542 } 1543 1544 @Override onConfigurationFailure(ITestResult itr)1545 public void onConfigurationFailure(ITestResult itr) { 1546 m_failedConfigurations.addResult(itr, itr.getMethod()); 1547 } 1548 1549 @Override onConfigurationSkip(ITestResult itr)1550 public void onConfigurationSkip(ITestResult itr) { 1551 m_skippedConfigurations.addResult(itr, itr.getMethod()); 1552 } 1553 1554 @Override onConfigurationSuccess(ITestResult itr)1555 public void onConfigurationSuccess(ITestResult itr) { 1556 m_passedConfigurations.addResult(itr, itr.getMethod()); 1557 } 1558 } 1559 1560 @Deprecated setMethodInterceptor(IMethodInterceptor methodInterceptor)1561 public void setMethodInterceptor(IMethodInterceptor methodInterceptor){ 1562 m_methodInterceptors.add(methodInterceptor); 1563 } 1564 addMethodInterceptor(IMethodInterceptor methodInterceptor)1565 public void addMethodInterceptor(IMethodInterceptor methodInterceptor){ 1566 m_methodInterceptors.add(methodInterceptor); 1567 } 1568 1569 @Override getCurrentXmlTest()1570 public XmlTest getCurrentXmlTest() { 1571 return m_xmlTest; 1572 } 1573 1574 private IAttributes m_attributes = new Attributes(); 1575 1576 @Override getAttribute(String name)1577 public Object getAttribute(String name) { 1578 return m_attributes.getAttribute(name); 1579 } 1580 1581 @Override setAttribute(String name, Object value)1582 public void setAttribute(String name, Object value) { 1583 m_attributes.setAttribute(name, value); 1584 } 1585 1586 @Override getAttributeNames()1587 public Set<String> getAttributeNames() { 1588 return m_attributes.getAttributeNames(); 1589 } 1590 1591 @Override removeAttribute(String name)1592 public Object removeAttribute(String name) { 1593 return m_attributes.removeAttribute(name); 1594 } 1595 1596 private ListMultiMap<Class<? extends Module>, Module> m_guiceModules = Maps.newListMultiMap(); 1597 1598 @Override getGuiceModules(Class<? extends Module> cls)1599 public List<Module> getGuiceModules(Class<? extends Module> cls) { 1600 List<Module> result = m_guiceModules.get(cls); 1601 return result; 1602 } 1603 addGuiceModule(Class<? extends Module> cls, Module module)1604 private void addGuiceModule(Class<? extends Module> cls, Module module) { 1605 m_guiceModules.put(cls, module); 1606 } 1607 1608 private Map<List<Module>, Injector> m_injectors = Maps.newHashMap(); 1609 1610 @Override getInjector(List<Module> moduleInstances)1611 public Injector getInjector(List<Module> moduleInstances) { 1612 return m_injectors .get(moduleInstances); 1613 } 1614 1615 @Override getInjector(IClass iClass)1616 public Injector getInjector(IClass iClass) { 1617 Annotation annotation = AnnotationHelper.findAnnotationSuperClasses(Guice.class, iClass.getRealClass()); 1618 if (annotation == null) return null; 1619 if (iClass instanceof TestClass) { 1620 iClass = ((TestClass)iClass).getIClass(); 1621 } 1622 if (!(iClass instanceof ClassImpl)) return null; 1623 Injector parentInjector = ((ClassImpl)iClass).getParentInjector(); 1624 1625 Guice guice = (Guice) annotation; 1626 List<Module> moduleInstances = Lists.newArrayList(getModules(guice, parentInjector, iClass.getRealClass())); 1627 1628 // Reuse the previous injector, if any 1629 Injector injector = getInjector(moduleInstances); 1630 if (injector == null) { 1631 injector = parentInjector.createChildInjector(moduleInstances); 1632 addInjector(moduleInstances, injector); 1633 } 1634 return injector; 1635 } 1636 getModules(Guice guice, Injector parentInjector, Class<?> testClass)1637 private Module[] getModules(Guice guice, Injector parentInjector, Class<?> testClass) { 1638 List<Module> result = Lists.newArrayList(); 1639 for (Class<? extends Module> moduleClass : guice.modules()) { 1640 List<Module> modules = getGuiceModules(moduleClass); 1641 if (modules != null && modules.size() > 0) { 1642 result.addAll(modules); 1643 } else { 1644 Module instance = parentInjector.getInstance(moduleClass); 1645 result.add(instance); 1646 addGuiceModule(moduleClass, instance); 1647 } 1648 } 1649 Class<? extends IModuleFactory> factory = guice.moduleFactory(); 1650 if (factory != IModuleFactory.class) { 1651 IModuleFactory factoryInstance = parentInjector.getInstance(factory); 1652 Module moduleClass = factoryInstance.createModule(this, testClass); 1653 if (moduleClass != null) { 1654 result.add(moduleClass); 1655 } 1656 } 1657 1658 return result.toArray(new Module[result.size()]); 1659 } 1660 1661 @Override addInjector(List<Module> moduleInstances, Injector injector)1662 public void addInjector(List<Module> moduleInstances, Injector injector) { 1663 m_injectors.put(moduleInstances, injector); 1664 } 1665 1666 } // TestRunner 1667