1 package org.testng; 2 3 import java.io.File; 4 import java.io.FileNotFoundException; 5 import java.io.IOException; 6 import java.io.InputStream; 7 import java.net.URLClassLoader; 8 import java.util.ArrayList; 9 import java.util.Arrays; 10 import java.util.Collection; 11 import java.util.Enumeration; 12 import java.util.List; 13 import java.util.Map; 14 import java.util.ServiceLoader; 15 import java.util.Set; 16 import java.util.concurrent.LinkedBlockingQueue; 17 import java.util.concurrent.TimeUnit; 18 import java.util.jar.JarEntry; 19 import java.util.jar.JarFile; 20 21 import javax.xml.parsers.ParserConfigurationException; 22 23 import org.testng.annotations.ITestAnnotation; 24 import org.testng.collections.Lists; 25 import org.testng.collections.Maps; 26 import org.testng.collections.Sets; 27 import org.testng.internal.ClassHelper; 28 import org.testng.internal.Configuration; 29 import org.testng.internal.DynamicGraph; 30 import org.testng.internal.IConfiguration; 31 import org.testng.internal.IPathUtils; 32 import org.testng.internal.IResultListener2; 33 import org.testng.internal.OverrideProcessor; 34 import org.testng.internal.PathUtilsFactory; 35 import org.testng.internal.SuiteRunnerMap; 36 import org.testng.internal.Utils; 37 import org.testng.internal.Version; 38 import org.testng.internal.annotations.DefaultAnnotationTransformer; 39 import org.testng.internal.annotations.IAnnotationFinder; 40 import org.testng.internal.annotations.JDK15AnnotationFinder; 41 import org.testng.internal.thread.graph.GraphThreadPoolExecutor; 42 import org.testng.internal.thread.graph.IThreadWorkerFactory; 43 import org.testng.internal.thread.graph.SuiteWorkerFactory; 44 import org.testng.junit.JUnitTestFinder; 45 import org.testng.log4testng.Logger; 46 import org.testng.remote.SuiteDispatcher; 47 import org.testng.remote.SuiteSlave; 48 import org.testng.reporters.EmailableReporter; 49 import org.testng.reporters.EmailableReporter2; 50 import org.testng.reporters.FailedReporter; 51 import org.testng.reporters.JUnitReportReporter; 52 import org.testng.reporters.SuiteHTMLReporter; 53 import org.testng.reporters.VerboseReporter; 54 import org.testng.reporters.XMLReporter; 55 import org.testng.reporters.jq.Main; 56 import org.testng.xml.Parser; 57 import org.testng.xml.XmlClass; 58 import org.testng.xml.XmlInclude; 59 import org.testng.xml.XmlMethodSelector; 60 import org.testng.xml.XmlSuite; 61 import org.testng.xml.XmlTest; 62 import org.xml.sax.SAXException; 63 64 import com.beust.jcommander.JCommander; 65 import com.beust.jcommander.ParameterException; 66 67 import static org.testng.internal.Utils.defaultIfStringEmpty; 68 import static org.testng.internal.Utils.isStringEmpty; 69 import static org.testng.internal.Utils.isStringNotEmpty; 70 71 /** 72 * This class is the main entry point for running tests in the TestNG framework. 73 * Users can create their own TestNG object and invoke it in many different 74 * ways: 75 * <ul> 76 * <li>On an existing testng.xml 77 * <li>On a synthetic testng.xml, created entirely from Java 78 * <li>By directly setting the test classes 79 * </ul> 80 * You can also define which groups to include or exclude, assign parameters, etc... 81 * <P/> 82 * The command line parameters are: 83 * <UL> 84 * <LI>-d <TT>outputdir</TT>: specify the output directory</LI> 85 * <LI>-testclass <TT>class_name</TT>: specifies one or several class names </li> 86 * <LI>-testjar <TT>jar_name</TT>: specifies the jar containing the tests</LI> 87 * <LI>-sourcedir <TT>src1;src2</TT>: ; separated list of source directories 88 * (used only when javadoc annotations are used)</LI> 89 * <LI>-target</LI> 90 * <LI>-groups</LI> 91 * <LI>-testrunfactory</LI> 92 * <LI>-listener</LI> 93 * </UL> 94 * <P/> 95 * Please consult documentation for more details. 96 * 97 * FIXME: should support more than simple paths for suite xmls 98 * 99 * @see #usage() 100 * 101 * @author <a href = "mailto:cedric@beust.com">Cedric Beust</a> 102 */ 103 public class TestNG { 104 105 /** This class' log4testng Logger. */ 106 private static final Logger LOGGER = Logger.getLogger(TestNG.class); 107 108 /** The default name for a suite launched from the command line */ 109 public static final String DEFAULT_COMMAND_LINE_SUITE_NAME = "Command line suite"; 110 111 /** The default name for a test launched from the command line */ 112 public static final String DEFAULT_COMMAND_LINE_TEST_NAME = "Command line test"; 113 114 /** The default name of the result's output directory (keep public, used by Eclipse). */ 115 public static final String DEFAULT_OUTPUTDIR = "test-output"; 116 117 /** System properties */ 118 public static final String SHOW_TESTNG_STACK_FRAMES = "testng.show.stack.frames"; 119 public static final String TEST_CLASSPATH = "testng.test.classpath"; 120 121 private static TestNG m_instance; 122 123 private static JCommander m_jCommander; 124 125 private List<String> m_commandLineMethods; 126 protected List<XmlSuite> m_suites = Lists.newArrayList(); 127 private List<XmlSuite> m_cmdlineSuites; 128 private String m_outputDir = DEFAULT_OUTPUTDIR; 129 130 private String[] m_includedGroups; 131 private String[] m_excludedGroups; 132 133 private Boolean m_isJUnit = XmlSuite.DEFAULT_JUNIT; 134 private Boolean m_isMixed = XmlSuite.DEFAULT_MIXED; 135 protected boolean m_useDefaultListeners = true; 136 137 private ITestRunnerFactory m_testRunnerFactory; 138 139 // These listeners can be overridden from the command line 140 private List<IClassListener> m_classListeners = Lists.newArrayList(); 141 private List<ITestListener> m_testListeners = Lists.newArrayList(); 142 private List<ISuiteListener> m_suiteListeners = Lists.newArrayList(); 143 private Set<IReporter> m_reporters = Sets.newHashSet(); 144 145 protected static final int HAS_FAILURE = 1; 146 protected static final int HAS_SKIPPED = 2; 147 protected static final int HAS_FSP = 4; 148 protected static final int HAS_NO_TEST = 8; 149 150 public static final Integer DEFAULT_VERBOSE = 1; 151 152 private int m_status; 153 private boolean m_hasTests= false; 154 155 private String m_slavefileName = null; 156 private String m_masterfileName = null; 157 158 // Command line suite parameters 159 private int m_threadCount; 160 private boolean m_useThreadCount; 161 private XmlSuite.ParallelMode m_parallelMode = XmlSuite.ParallelMode.FALSE; 162 private String m_configFailurePolicy; 163 private Class[] m_commandLineTestClasses; 164 165 private String m_defaultSuiteName=DEFAULT_COMMAND_LINE_SUITE_NAME; 166 private String m_defaultTestName=DEFAULT_COMMAND_LINE_TEST_NAME; 167 168 private Map<String, Integer> m_methodDescriptors = Maps.newHashMap(); 169 170 private ITestObjectFactory m_objectFactory; 171 172 private List<IInvokedMethodListener> m_invokedMethodListeners = Lists.newArrayList(); 173 174 private Integer m_dataProviderThreadCount = null; 175 176 private String m_jarPath; 177 /** The path of the testng.xml file inside the jar file */ 178 private String m_xmlPathInJar = CommandLineArgs.XML_PATH_IN_JAR_DEFAULT; 179 180 private List<String> m_stringSuites = Lists.newArrayList(); 181 182 private IHookable m_hookable; 183 private IConfigurable m_configurable; 184 185 protected long m_end; 186 protected long m_start; 187 188 private List<IExecutionListener> m_executionListeners = Lists.newArrayList(); 189 190 private List<IAlterSuiteListener> m_alterSuiteListeners= Lists.newArrayList(); 191 192 private boolean m_isInitialized = false; 193 194 private IPathUtils m_pathUtils = PathUtilsFactory.newInstance(); 195 196 /** 197 * Default constructor. Setting also usage of default listeners/reporters. 198 */ TestNG()199 public TestNG() { 200 init(true); 201 } 202 203 /** 204 * Used by maven2 to have 0 output of any kind come out 205 * of testng. 206 * @param useDefaultListeners Whether or not any default reports 207 * should be added to tests. 208 */ TestNG(boolean useDefaultListeners)209 public TestNG(boolean useDefaultListeners) { 210 init(useDefaultListeners); 211 } 212 init(boolean useDefaultListeners)213 private void init(boolean useDefaultListeners) { 214 m_instance = this; 215 216 m_useDefaultListeners = useDefaultListeners; 217 m_configuration = new Configuration(); 218 } 219 getStatus()220 public int getStatus() { 221 return m_status; 222 } 223 setStatus(int status)224 private void setStatus(int status) { 225 m_status |= status; 226 } 227 228 /** 229 * Sets the output directory where the reports will be created. 230 * @param outputdir The directory. 231 */ setOutputDirectory(final String outputdir)232 public void setOutputDirectory(final String outputdir) { 233 if (isStringNotEmpty(outputdir)) { 234 m_outputDir = outputdir; 235 } 236 } 237 238 /** 239 * If this method is passed true before run(), the default listeners 240 * will not be used. 241 * <ul> 242 * <li>org.testng.reporters.TestHTMLReporter 243 * <li>org.testng.reporters.JUnitXMLReporter 244 * <li>org.testng.reporters.XMLReporter 245 * </ul> 246 * 247 * @see org.testng.reporters.TestHTMLReporter 248 * @see org.testng.reporters.JUnitXMLReporter 249 * @see org.testng.reporters.XMLReporter 250 */ setUseDefaultListeners(boolean useDefaultListeners)251 public void setUseDefaultListeners(boolean useDefaultListeners) { 252 m_useDefaultListeners = useDefaultListeners; 253 } 254 255 /** 256 * Sets a jar containing a testng.xml file. 257 * 258 * @param jarPath 259 */ setTestJar(String jarPath)260 public void setTestJar(String jarPath) { 261 m_jarPath = jarPath; 262 } 263 264 /** 265 * Sets the path to the XML file in the test jar file. 266 */ setXmlPathInJar(String xmlPathInJar)267 public void setXmlPathInJar(String xmlPathInJar) { 268 m_xmlPathInJar = xmlPathInJar; 269 } 270 initializeSuitesAndJarFile()271 public void initializeSuitesAndJarFile() { 272 // The Eclipse plug-in (RemoteTestNG) might have invoked this method already 273 // so don't initialize suites twice. 274 if (m_isInitialized) { 275 return; 276 } 277 278 m_isInitialized = true; 279 if (m_suites.size() > 0) { 280 //to parse the suite files (<suite-file>), if any 281 for (XmlSuite s: m_suites) { 282 for (String suiteFile : s.getSuiteFiles()) { 283 try { 284 Collection<XmlSuite> childSuites = getParser(m_pathUtils.getSuiteNormalizedPath(s, suiteFile)).parse(); 285 for (XmlSuite cSuite : childSuites){ 286 cSuite.setParentSuite(s); 287 s.getChildSuites().add(cSuite); 288 } 289 } catch (ParserConfigurationException | IOException | SAXException e) { 290 e.printStackTrace(System.out); 291 } 292 } 293 294 } 295 return; 296 } 297 298 // 299 // Parse the suites that were passed on the command line 300 // 301 for (String suitePath : m_stringSuites) { 302 if(LOGGER.isDebugEnabled()) { 303 LOGGER.debug("suiteXmlPath: \"" + suitePath + "\""); 304 } 305 try { 306 Collection<XmlSuite> allSuites = getParser(suitePath).parse(); 307 308 for (XmlSuite s : allSuites) { 309 // If test names were specified, only run these test names 310 if (m_testNames != null) { 311 m_suites.add(extractTestNames(s, m_testNames)); 312 } 313 else { 314 m_suites.add(s); 315 } 316 } 317 } 318 catch(SAXException | ParserConfigurationException | IOException e) { 319 e.printStackTrace(System.out); 320 } catch(Exception ex) { 321 // Probably a Yaml exception, unnest it 322 Throwable t = ex; 323 while (t.getCause() != null) t = t.getCause(); 324 // t.printStackTrace(); 325 if (t instanceof TestNGException) throw (TestNGException) t; 326 else throw new TestNGException(t); 327 } 328 } 329 330 // 331 // jar path 332 // 333 // If suites were passed on the command line, they take precedence over the suite file 334 // inside that jar path 335 if (m_jarPath != null && m_stringSuites.size() > 0) { 336 StringBuilder suites = new StringBuilder(); 337 for (String s : m_stringSuites) { 338 suites.append(s); 339 } 340 Utils.log("TestNG", 2, "Ignoring the XML file inside " + m_jarPath + " and using " 341 + suites + " instead"); 342 return; 343 } 344 if (isStringEmpty(m_jarPath)) { 345 return; 346 } 347 348 // We have a jar file and no XML file was specified: try to find an XML file inside the jar 349 File jarFile = new File(m_jarPath); 350 351 try { 352 353 Utils.log("TestNG", 2, "Trying to open jar file:" + jarFile); 354 355 boolean foundTestngXml = false; 356 List<String> classes = Lists.newArrayList(); 357 try (JarFile jf = new JarFile(jarFile)) { 358 // System.out.println(" result: " + jf); 359 Enumeration<JarEntry> entries = jf.entries(); 360 while (entries.hasMoreElements()) { 361 JarEntry je = entries.nextElement(); 362 if (je.getName().equals(m_xmlPathInJar)) { 363 Parser parser = getParser(jf.getInputStream(je)); 364 Collection<XmlSuite> suites = parser.parse(); 365 for (XmlSuite suite : suites) { 366 // If test names were specified, only run these test names 367 if (m_testNames != null) { 368 m_suites.add(extractTestNames(suite, m_testNames)); 369 } else { 370 m_suites.add(suite); 371 } 372 } 373 374 foundTestngXml = true; 375 break; 376 } else if (je.getName().endsWith(".class")) { 377 int n = je.getName().length() - ".class".length(); 378 classes.add(je.getName().replace("/", ".").substring(0, n)); 379 } 380 } 381 } 382 if (! foundTestngXml) { 383 Utils.log("TestNG", 1, 384 "Couldn't find the " + m_xmlPathInJar + " in the jar file, running all the classes"); 385 XmlSuite xmlSuite = new XmlSuite(); 386 xmlSuite.setVerbose(0); 387 xmlSuite.setName("Jar suite"); 388 XmlTest xmlTest = new XmlTest(xmlSuite); 389 List<XmlClass> xmlClasses = Lists.newArrayList(); 390 for (String cls : classes) { 391 XmlClass xmlClass = new XmlClass(cls); 392 xmlClasses.add(xmlClass); 393 } 394 xmlTest.setXmlClasses(xmlClasses); 395 m_suites.add(xmlSuite); 396 } 397 } 398 catch(ParserConfigurationException | IOException | SAXException ex) { 399 ex.printStackTrace(); 400 } 401 } 402 getParser(String path)403 private Parser getParser(String path) { 404 Parser result = new Parser(path); 405 initProcessor(result); 406 return result; 407 } 408 getParser(InputStream is)409 private Parser getParser(InputStream is) { 410 Parser result = new Parser(is); 411 initProcessor(result); 412 return result; 413 } 414 initProcessor(Parser result)415 private void initProcessor(Parser result) { 416 result.setPostProcessor(new OverrideProcessor(m_includedGroups, m_excludedGroups)); 417 } 418 419 /** 420 * If the XmlSuite contains at least one test named as testNames, return 421 * an XmlSuite that's made only of these tests, otherwise, return the 422 * original suite. 423 */ extractTestNames(XmlSuite s, List<String> testNames)424 private static XmlSuite extractTestNames(XmlSuite s, List<String> testNames) { 425 extractTestNamesFromChildSuites(s, testNames); 426 427 List<XmlTest> tests = Lists.newArrayList(); 428 for (XmlTest xt : s.getTests()) { 429 for (String tn : testNames) { 430 if (xt.getName().equals(tn)) { 431 tests.add(xt); 432 } 433 } 434 } 435 436 if (tests.size() == 0) { 437 return s; 438 } 439 else { 440 XmlSuite result = (XmlSuite) s.clone(); 441 result.getTests().clear(); 442 result.getTests().addAll(tests); 443 return result; 444 } 445 } 446 extractTestNamesFromChildSuites(XmlSuite s, List<String> testNames)447 private static void extractTestNamesFromChildSuites(XmlSuite s, List<String> testNames) { 448 List<XmlSuite> childSuites = s.getChildSuites(); 449 for (int i = 0; i < childSuites.size(); i++) { 450 XmlSuite child = childSuites.get(i); 451 XmlSuite extracted = extractTestNames(child, testNames); 452 // if a new xml suite is created, which means some tests was extracted, then we replace the child 453 if (extracted != child) { 454 childSuites.set(i, extracted); 455 } 456 } 457 } 458 459 /** 460 * Define the number of threads in the thread pool. 461 */ setThreadCount(int threadCount)462 public void setThreadCount(int threadCount) { 463 if(threadCount < 1) { 464 exitWithError("Cannot use a threadCount parameter less than 1; 1 > " + threadCount); 465 } 466 467 m_threadCount = threadCount; 468 m_useThreadCount = true; 469 } 470 471 /** 472 * Define whether this run will be run in parallel mode. 473 * @deprecated Use #setParallel(XmlSuite.ParallelMode) instead 474 */ 475 @Deprecated setParallel(String parallel)476 public void setParallel(String parallel) { 477 if (parallel == null) { 478 setParallel(XmlSuite.ParallelMode.FALSE); 479 } else { 480 setParallel(XmlSuite.ParallelMode.getValidParallel(parallel)); 481 } 482 } 483 setParallel(XmlSuite.ParallelMode parallel)484 public void setParallel(XmlSuite.ParallelMode parallel) { 485 m_parallelMode = parallel; 486 } 487 setCommandLineSuite(XmlSuite suite)488 public void setCommandLineSuite(XmlSuite suite) { 489 m_cmdlineSuites = Lists.newArrayList(); 490 m_cmdlineSuites.add(suite); 491 m_suites.add(suite); 492 } 493 494 /** 495 * Set the test classes to be run by this TestNG object. This method 496 * will create a dummy suite that will wrap these classes called 497 * "Command Line Test". 498 * <p/> 499 * If used together with threadCount, parallel, groups, excludedGroups than this one must be set first. 500 * 501 * @param classes An array of classes that contain TestNG annotations. 502 */ setTestClasses(Class[] classes)503 public void setTestClasses(Class[] classes) { 504 m_suites.clear(); 505 m_commandLineTestClasses = classes; 506 } 507 508 /** 509 * Given a string com.example.Foo.f1, return an array where [0] is the class and [1] 510 * is the method. 511 */ splitMethod(String m)512 private String[] splitMethod(String m) { 513 int index = m.lastIndexOf("."); 514 if (index < 0) { 515 throw new TestNGException("Bad format for command line method:" + m 516 + ", expected <class>.<method>"); 517 } 518 519 return new String[] { m.substring(0, index), m.substring(index + 1).replaceAll("\\*", "\\.\\*") }; 520 } 521 522 /** 523 * @return a list of XmlSuite objects that represent the list of classes and methods passed 524 * in parameter. 525 * 526 * @param commandLineMethods a string with the form "com.example.Foo.f1,com.example.Bar.f2" 527 */ createCommandLineSuitesForMethods(List<String> commandLineMethods)528 private List<XmlSuite> createCommandLineSuitesForMethods(List<String> commandLineMethods) { 529 // 530 // Create the <classes> tag 531 // 532 Set<Class> classes = Sets.newHashSet(); 533 for (String m : commandLineMethods) { 534 Class c = ClassHelper.forName(splitMethod(m)[0]); 535 if (c != null) { 536 classes.add(c); 537 } 538 } 539 540 List<XmlSuite> result = createCommandLineSuitesForClasses(classes.toArray(new Class[0])); 541 542 // 543 // Add the method tags 544 // 545 List<XmlClass> xmlClasses = Lists.newArrayList(); 546 for (XmlSuite s : result) { 547 for (XmlTest t : s.getTests()) { 548 xmlClasses.addAll(t.getClasses()); 549 } 550 } 551 552 for (XmlClass xc : xmlClasses) { 553 for (String m : commandLineMethods) { 554 String[] split = splitMethod(m); 555 String className = split[0]; 556 if (xc.getName().equals(className)) { 557 XmlInclude includedMethod = new XmlInclude(split[1]); 558 xc.getIncludedMethods().add(includedMethod); 559 } 560 } 561 } 562 563 return result; 564 } 565 createCommandLineSuitesForClasses(Class[] classes)566 private List<XmlSuite> createCommandLineSuitesForClasses(Class[] classes) { 567 // 568 // See if any of the classes has an xmlSuite or xmlTest attribute. 569 // If it does, create the appropriate XmlSuite, otherwise, create 570 // the default one 571 // 572 XmlClass[] xmlClasses = Utils.classesToXmlClasses(classes); 573 Map<String, XmlSuite> suites = Maps.newHashMap(); 574 IAnnotationFinder finder = m_configuration.getAnnotationFinder(); 575 576 for (int i = 0; i < classes.length; i++) { 577 Class c = classes[i]; 578 ITestAnnotation test = finder.findAnnotation(c, ITestAnnotation.class); 579 String suiteName = getDefaultSuiteName(); 580 String testName = getDefaultTestName(); 581 boolean isJUnit = false; 582 if (test != null) { 583 suiteName = defaultIfStringEmpty(test.getSuiteName(), suiteName); 584 testName = defaultIfStringEmpty(test.getTestName(), testName); 585 } else { 586 if (m_isMixed && JUnitTestFinder.isJUnitTest(c)) { 587 isJUnit = true; 588 testName = c.getName(); 589 } 590 } 591 XmlSuite xmlSuite = suites.get(suiteName); 592 if (xmlSuite == null) { 593 xmlSuite = new XmlSuite(); 594 xmlSuite.setName(suiteName); 595 suites.put(suiteName, xmlSuite); 596 } 597 598 if (m_dataProviderThreadCount != null) { 599 xmlSuite.setDataProviderThreadCount(m_dataProviderThreadCount); 600 } 601 XmlTest xmlTest = null; 602 for (XmlTest xt : xmlSuite.getTests()) { 603 if (xt.getName().equals(testName)) { 604 xmlTest = xt; 605 break; 606 } 607 } 608 609 if (xmlTest == null) { 610 xmlTest = new XmlTest(xmlSuite); 611 xmlTest.setName(testName); 612 xmlTest.setJUnit(isJUnit); 613 } 614 615 xmlTest.getXmlClasses().add(xmlClasses[i]); 616 } 617 618 return new ArrayList<>(suites.values()); 619 } 620 addMethodSelector(String className, int priority)621 public void addMethodSelector(String className, int priority) { 622 m_methodDescriptors.put(className, priority); 623 } 624 625 /** 626 * Set the suites file names to be run by this TestNG object. This method tries to load and 627 * parse the specified TestNG suite xml files. If a file is missing, it is ignored. 628 * 629 * @param suites A list of paths to one more XML files defining the tests. For example: 630 * 631 * <pre> 632 * TestNG tng = new TestNG(); 633 * List<String> suites = Lists.newArrayList(); 634 * suites.add("c:/tests/testng1.xml"); 635 * suites.add("c:/tests/testng2.xml"); 636 * tng.setTestSuites(suites); 637 * tng.run(); 638 * </pre> 639 */ setTestSuites(List<String> suites)640 public void setTestSuites(List<String> suites) { 641 m_stringSuites = suites; 642 } 643 644 /** 645 * Specifies the XmlSuite objects to run. 646 * @param suites 647 * @see org.testng.xml.XmlSuite 648 */ setXmlSuites(List<XmlSuite> suites)649 public void setXmlSuites(List<XmlSuite> suites) { 650 m_suites = suites; 651 } 652 653 /** 654 * Define which groups will be excluded from this run. 655 * 656 * @param groups A list of group names separated by a comma. 657 */ setExcludedGroups(String groups)658 public void setExcludedGroups(String groups) { 659 m_excludedGroups = Utils.split(groups, ","); 660 } 661 662 663 /** 664 * Define which groups will be included from this run. 665 * 666 * @param groups A list of group names separated by a comma. 667 */ setGroups(String groups)668 public void setGroups(String groups) { 669 m_includedGroups = Utils.split(groups, ","); 670 } 671 672 setTestRunnerFactoryClass(Class testRunnerFactoryClass)673 private void setTestRunnerFactoryClass(Class testRunnerFactoryClass) { 674 setTestRunnerFactory((ITestRunnerFactory) ClassHelper.newInstance(testRunnerFactoryClass)); 675 } 676 677 setTestRunnerFactory(ITestRunnerFactory itrf)678 protected void setTestRunnerFactory(ITestRunnerFactory itrf) { 679 m_testRunnerFactory= itrf; 680 } 681 setObjectFactory(Class c)682 public void setObjectFactory(Class c) { 683 m_objectFactory = (ITestObjectFactory) ClassHelper.newInstance(c); 684 } 685 setObjectFactory(ITestObjectFactory factory)686 public void setObjectFactory(ITestObjectFactory factory) { 687 m_objectFactory = factory; 688 } 689 690 /** 691 * Define which listeners to user for this run. 692 * 693 * @param classes A list of classes, which must be either ISuiteListener, 694 * ITestListener or IReporter 695 */ setListenerClasses(List<Class> classes)696 public void setListenerClasses(List<Class> classes) { 697 for (Class cls: classes) { 698 addListener(ClassHelper.newInstance(cls)); 699 } 700 } 701 addListener(Object listener)702 public void addListener(Object listener) { 703 if (! (listener instanceof ITestNGListener)) 704 { 705 exitWithError("Listener " + listener 706 + " must be one of ITestListener, ISuiteListener, IReporter, " 707 + " IAnnotationTransformer, IMethodInterceptor or IInvokedMethodListener"); 708 } 709 else { 710 if (listener instanceof ISuiteListener) { 711 addListener((ISuiteListener) listener); 712 } 713 if (listener instanceof ITestListener) { 714 addListener((ITestListener) listener); 715 } 716 if (listener instanceof IClassListener) { 717 addListener((IClassListener) listener); 718 } 719 if (listener instanceof IReporter) { 720 addListener((IReporter) listener); 721 } 722 if (listener instanceof IAnnotationTransformer) { 723 setAnnotationTransformer((IAnnotationTransformer) listener); 724 } 725 if (listener instanceof IMethodInterceptor) { 726 m_methodInterceptors.add((IMethodInterceptor) listener); 727 } 728 if (listener instanceof IInvokedMethodListener) { 729 addInvokedMethodListener((IInvokedMethodListener) listener); 730 } 731 if (listener instanceof IHookable) { 732 setHookable((IHookable) listener); 733 } 734 if (listener instanceof IConfigurable) { 735 setConfigurable((IConfigurable) listener); 736 } 737 if (listener instanceof IExecutionListener) { 738 addExecutionListener((IExecutionListener) listener); 739 } 740 if (listener instanceof IConfigurationListener) { 741 getConfiguration().addConfigurationListener((IConfigurationListener) listener); 742 } 743 if (listener instanceof IAlterSuiteListener) { 744 addAlterSuiteListener((IAlterSuiteListener) listener); 745 } 746 } 747 } 748 addListener(IInvokedMethodListener listener)749 public void addListener(IInvokedMethodListener listener) { 750 m_invokedMethodListeners.add(listener); 751 } 752 addListener(ISuiteListener listener)753 public void addListener(ISuiteListener listener) { 754 if (null != listener) { 755 m_suiteListeners.add(listener); 756 } 757 } 758 addListener(ITestListener listener)759 public void addListener(ITestListener listener) { 760 if (null != listener) { 761 m_testListeners.add(listener); 762 } 763 } 764 addListener(IClassListener listener)765 public void addListener(IClassListener listener) { 766 if (null != listener) { 767 m_classListeners.add(listener); 768 } 769 } 770 addListener(IReporter listener)771 public void addListener(IReporter listener) { 772 if (null != listener) { 773 m_reporters.add(listener); 774 } 775 } 776 addInvokedMethodListener(IInvokedMethodListener listener)777 public void addInvokedMethodListener(IInvokedMethodListener listener) { 778 m_invokedMethodListeners.add(listener); 779 } 780 getReporters()781 public Set<IReporter> getReporters() { 782 return m_reporters; 783 } 784 getTestListeners()785 public List<ITestListener> getTestListeners() { 786 return m_testListeners; 787 } 788 getSuiteListeners()789 public List<ISuiteListener> getSuiteListeners() { 790 return m_suiteListeners; 791 } 792 793 /** If m_verbose gets set, it will override the verbose setting in testng.xml */ 794 private Integer m_verbose = null; 795 796 private final IAnnotationTransformer m_defaultAnnoProcessor = new DefaultAnnotationTransformer(); 797 private IAnnotationTransformer m_annotationTransformer = m_defaultAnnoProcessor; 798 799 private Boolean m_skipFailedInvocationCounts = false; 800 801 private List<IMethodInterceptor> m_methodInterceptors = new ArrayList<IMethodInterceptor>(); 802 803 /** The list of test names to run from the given suite */ 804 private List<String> m_testNames; 805 806 private Integer m_suiteThreadPoolSize = CommandLineArgs.SUITE_THREAD_POOL_SIZE_DEFAULT; 807 808 private boolean m_randomizeSuites = Boolean.FALSE; 809 810 private boolean m_preserveOrder = false; 811 private Boolean m_groupByInstances; 812 813 private IConfiguration m_configuration; 814 815 /** 816 * Sets the level of verbosity. This value will override the value specified 817 * in the test suites. 818 * 819 * @param verbose the verbosity level (0 to 10 where 10 is most detailed) 820 * Actually, this is a lie: you can specify -1 and this will put TestNG 821 * in debug mode (no longer slicing off stack traces and all). 822 */ setVerbose(int verbose)823 public void setVerbose(int verbose) { 824 m_verbose = verbose; 825 } 826 initializeCommandLineSuites()827 private void initializeCommandLineSuites() { 828 if (m_commandLineTestClasses != null || m_commandLineMethods != null) { 829 if (null != m_commandLineMethods) { 830 m_cmdlineSuites = createCommandLineSuitesForMethods(m_commandLineMethods); 831 } 832 else { 833 m_cmdlineSuites = createCommandLineSuitesForClasses(m_commandLineTestClasses); 834 } 835 836 for (XmlSuite s : m_cmdlineSuites) { 837 for (XmlTest t : s.getTests()) { 838 t.setPreserveOrder(String.valueOf(m_preserveOrder)); 839 } 840 m_suites.add(s); 841 if (m_groupByInstances != null) { 842 s.setGroupByInstances(m_groupByInstances); 843 } 844 } 845 } 846 } 847 initializeCommandLineSuitesParams()848 private void initializeCommandLineSuitesParams() { 849 if(null == m_cmdlineSuites) { 850 return; 851 } 852 853 for (XmlSuite s : m_cmdlineSuites) { 854 if(m_useThreadCount) { 855 s.setThreadCount(m_threadCount); 856 } 857 s.setParallel(m_parallelMode); 858 if(m_configFailurePolicy != null) { 859 s.setConfigFailurePolicy(m_configFailurePolicy.toString()); 860 } 861 } 862 863 } 864 initializeCommandLineSuitesGroups()865 private void initializeCommandLineSuitesGroups() { 866 // If groups were specified on the command line, they should override groups 867 // specified in the XML file 868 boolean hasIncludedGroups = null != m_includedGroups && m_includedGroups.length > 0; 869 boolean hasExcludedGroups = null != m_excludedGroups && m_excludedGroups.length > 0; 870 List<XmlSuite> suites = m_cmdlineSuites != null ? m_cmdlineSuites : m_suites; 871 if (hasIncludedGroups || hasExcludedGroups) { 872 for (XmlSuite s : suites) { 873 //set on each test, instead of just the first one of the suite 874 for (XmlTest t : s.getTests()) { 875 if(hasIncludedGroups) { 876 t.setIncludedGroups(Arrays.asList(m_includedGroups)); 877 } 878 if(hasExcludedGroups) { 879 t.setExcludedGroups(Arrays.asList(m_excludedGroups)); 880 } 881 } 882 } 883 } 884 } addReporter(Class<? extends IReporter> r)885 private void addReporter(Class<? extends IReporter> r) { 886 m_reporters.add(ClassHelper.newInstance(r)); 887 } 888 initializeDefaultListeners()889 private void initializeDefaultListeners() { 890 m_testListeners.add(new ExitCodeListener(this)); 891 892 if (m_useDefaultListeners) { 893 addReporter(SuiteHTMLReporter.class); 894 addReporter(Main.class); 895 addReporter(FailedReporter.class); 896 addReporter(XMLReporter.class); 897 if (System.getProperty("oldTestngEmailableReporter") != null) { 898 addReporter(EmailableReporter.class); 899 } else if (System.getProperty("noEmailableReporter") == null) { 900 addReporter(EmailableReporter2.class); 901 } 902 addReporter(JUnitReportReporter.class); 903 if (m_verbose != null && m_verbose > 4) { 904 addListener(new VerboseReporter("[TestNG] ")); 905 } 906 } 907 } 908 initializeConfiguration()909 private void initializeConfiguration() { 910 ITestObjectFactory factory = m_objectFactory; 911 // 912 // Install the listeners found in ServiceLoader (or use the class 913 // loader for tests, if specified). 914 // 915 addServiceLoaderListeners(); 916 917 // 918 // Install the listeners found in the suites 919 // 920 for (XmlSuite s : m_suites) { 921 for (String listenerName : s.getListeners()) { 922 Class<?> listenerClass = ClassHelper.forName(listenerName); 923 924 // If specified listener does not exist, a TestNGException will be thrown 925 if(listenerClass == null) { 926 throw new TestNGException("Listener " + listenerName 927 + " was not found in project's classpath"); 928 } 929 930 Object listener = ClassHelper.newInstance(listenerClass); 931 addListener(listener); 932 } 933 934 // 935 // Install the method selectors 936 // 937 for (XmlMethodSelector methodSelector : s.getMethodSelectors() ) { 938 addMethodSelector(methodSelector.getClassName(), methodSelector.getPriority()); 939 } 940 941 // 942 // Find if we have an object factory 943 // 944 if (s.getObjectFactory() != null) { 945 if (factory == null) { 946 factory = s.getObjectFactory(); 947 } else { 948 throw new TestNGException("Found more than one object-factory tag in your suites"); 949 } 950 } 951 } 952 953 m_configuration.setAnnotationFinder(new JDK15AnnotationFinder(getAnnotationTransformer())); 954 m_configuration.setHookable(m_hookable); 955 m_configuration.setConfigurable(m_configurable); 956 m_configuration.setObjectFactory(factory); 957 } 958 959 /** 960 * Using reflection to remain Java 5 compliant. 961 */ addServiceLoaderListeners()962 private void addServiceLoaderListeners() { 963 Iterable<ITestNGListener> loader = m_serviceLoaderClassLoader != null ? 964 ServiceLoader.load(ITestNGListener.class, m_serviceLoaderClassLoader) 965 : ServiceLoader.load(ITestNGListener.class); 966 for (ITestNGListener l : loader) { 967 Utils.log("[TestNG]", 2, "Adding ServiceLoader listener:" + l); 968 addListener(l); 969 addServiceLoaderListener(l); 970 } 971 } 972 973 /** 974 * Before suites are executed, do a sanity check to ensure all required 975 * conditions are met. If not, throw an exception to stop test execution 976 * 977 * @throws TestNGException if the sanity check fails 978 */ sanityCheck()979 private void sanityCheck() { 980 checkTestNames(m_suites); 981 checkSuiteNames(m_suites); 982 } 983 984 /** 985 * Ensure that two XmlTest within the same XmlSuite don't have the same name 986 */ checkTestNames(List<XmlSuite> suites)987 private void checkTestNames(List<XmlSuite> suites) { 988 for (XmlSuite suite : suites) { 989 Set<String> testNames = Sets.newHashSet(); 990 for (XmlTest test : suite.getTests()) { 991 if (testNames.contains(test.getName())) { 992 throw new TestNGException("Two tests in the same suite " 993 + "cannot have the same name: " + test.getName()); 994 } else { 995 testNames.add(test.getName()); 996 } 997 } 998 checkTestNames(suite.getChildSuites()); 999 } 1000 } 1001 1002 /** 1003 * Ensure that two XmlSuite don't have the same name 1004 * Otherwise will be clash in SuiteRunnerMap 1005 * See issue #302 1006 */ checkSuiteNames(List<XmlSuite> suites)1007 private void checkSuiteNames(List<XmlSuite> suites) { 1008 checkSuiteNamesInternal(suites, Sets.<String>newHashSet()); 1009 } 1010 checkSuiteNamesInternal(List<XmlSuite> suites, Set<String> names)1011 private void checkSuiteNamesInternal(List<XmlSuite> suites, Set<String> names) { 1012 for (XmlSuite suite : suites) { 1013 final String name = suite.getName(); 1014 1015 int count = 0; 1016 String tmpName = name; 1017 while (names.contains(tmpName)) { 1018 tmpName = name + " (" + count++ + ")"; 1019 } 1020 1021 if (count > 0) { 1022 suite.setName(tmpName); 1023 names.add(tmpName); 1024 } else { 1025 names.add(name); 1026 } 1027 1028 names.add(name); 1029 checkSuiteNamesInternal(suite.getChildSuites(), names); 1030 } 1031 } 1032 1033 /** 1034 * Run TestNG. 1035 */ run()1036 public void run() { 1037 initializeSuitesAndJarFile(); 1038 initializeConfiguration(); 1039 initializeDefaultListeners(); 1040 initializeCommandLineSuites(); 1041 initializeCommandLineSuitesParams(); 1042 initializeCommandLineSuitesGroups(); 1043 1044 sanityCheck(); 1045 1046 List<ISuite> suiteRunners = null; 1047 1048 runSuiteAlterationListeners(); 1049 runExecutionListeners(true /* start */); 1050 1051 m_start = System.currentTimeMillis(); 1052 1053 // 1054 // Slave mode 1055 // 1056 if (m_slavefileName != null) { 1057 SuiteSlave slave = new SuiteSlave( m_slavefileName, this ); 1058 slave.waitForSuites(); 1059 } 1060 1061 // 1062 // Regular mode 1063 // 1064 else if (m_masterfileName == null) { 1065 suiteRunners = runSuitesLocally(); 1066 } 1067 1068 // 1069 // Master mode 1070 // 1071 else { 1072 SuiteDispatcher dispatcher = new SuiteDispatcher(m_masterfileName); 1073 suiteRunners = dispatcher.dispatch(getConfiguration(), 1074 m_suites, getOutputDirectory(), 1075 getTestListeners()); 1076 } 1077 1078 m_end = System.currentTimeMillis(); 1079 runExecutionListeners(false /* finish */); 1080 1081 if(null != suiteRunners) { 1082 generateReports(suiteRunners); 1083 } 1084 1085 if(!m_hasTests) { 1086 setStatus(HAS_NO_TEST); 1087 if (TestRunner.getVerbose() > 1) { 1088 System.err.println("[TestNG] No tests found. Nothing was run"); 1089 usage(); 1090 } 1091 } 1092 } 1093 p(String string)1094 private void p(String string) { 1095 System.out.println("[TestNG] " + string); 1096 } 1097 runSuiteAlterationListeners()1098 private void runSuiteAlterationListeners() { 1099 for (List<IAlterSuiteListener> listeners 1100 : Arrays.asList(m_alterSuiteListeners, m_configuration.getAlterSuiteListeners())) { 1101 for (IAlterSuiteListener l : listeners) { 1102 l.alter(m_suites); 1103 } 1104 } 1105 } 1106 runExecutionListeners(boolean start)1107 private void runExecutionListeners(boolean start) { 1108 for (List<IExecutionListener> listeners 1109 : Arrays.asList(m_executionListeners, m_configuration.getExecutionListeners())) { 1110 for (IExecutionListener l : listeners) { 1111 if (start) l.onExecutionStart(); 1112 else l.onExecutionFinish(); 1113 } 1114 } 1115 } 1116 addAlterSuiteListener(IAlterSuiteListener l)1117 public void addAlterSuiteListener(IAlterSuiteListener l) { 1118 m_alterSuiteListeners.add(l); 1119 } 1120 addExecutionListener(IExecutionListener l)1121 public void addExecutionListener(IExecutionListener l) { 1122 m_executionListeners.add(l); 1123 } 1124 usage()1125 private static void usage() { 1126 if (m_jCommander == null) { 1127 m_jCommander = new JCommander(new CommandLineArgs()); 1128 } 1129 m_jCommander.usage(); 1130 } 1131 generateReports(List<ISuite> suiteRunners)1132 private void generateReports(List<ISuite> suiteRunners) { 1133 for (IReporter reporter : m_reporters) { 1134 try { 1135 long start = System.currentTimeMillis(); 1136 reporter.generateReport(m_suites, suiteRunners, m_outputDir); 1137 Utils.log("TestNG", 2, "Time taken by " + reporter + ": " 1138 + (System.currentTimeMillis() - start) + " ms"); 1139 } 1140 catch(Exception ex) { 1141 System.err.println("[TestNG] Reporter " + reporter + " failed"); 1142 ex.printStackTrace(System.err); 1143 } 1144 } 1145 } 1146 1147 /** 1148 * This needs to be public for maven2, for now..At least 1149 * until an alternative mechanism is found. 1150 */ runSuitesLocally()1151 public List<ISuite> runSuitesLocally() { 1152 SuiteRunnerMap suiteRunnerMap = new SuiteRunnerMap(); 1153 if (m_suites.size() > 0) { 1154 if (m_suites.get(0).getVerbose() >= 2) { 1155 Version.displayBanner(); 1156 } 1157 1158 // First initialize the suite runners to ensure there are no configuration issues. 1159 // Create a map with XmlSuite as key and corresponding SuiteRunner as value 1160 for (XmlSuite xmlSuite : m_suites) { 1161 createSuiteRunners(suiteRunnerMap, xmlSuite); 1162 } 1163 1164 // 1165 // Run suites 1166 // 1167 if (m_suiteThreadPoolSize == 1 && !m_randomizeSuites) { 1168 // Single threaded and not randomized: run the suites in order 1169 for (XmlSuite xmlSuite : m_suites) { 1170 runSuitesSequentially(xmlSuite, suiteRunnerMap, getVerbose(xmlSuite), 1171 getDefaultSuiteName()); 1172 } 1173 } else { 1174 // Multithreaded: generate a dynamic graph that stores the suite hierarchy. This is then 1175 // used to run related suites in specific order. Parent suites are run only 1176 // once all the child suites have completed execution 1177 DynamicGraph<ISuite> suiteGraph = new DynamicGraph<>(); 1178 for (XmlSuite xmlSuite : m_suites) { 1179 populateSuiteGraph(suiteGraph, suiteRunnerMap, xmlSuite); 1180 } 1181 1182 IThreadWorkerFactory<ISuite> factory = new SuiteWorkerFactory(suiteRunnerMap, 1183 0 /* verbose hasn't been set yet */, getDefaultSuiteName()); 1184 GraphThreadPoolExecutor<ISuite> pooledExecutor = 1185 new GraphThreadPoolExecutor<>(suiteGraph, factory, m_suiteThreadPoolSize, 1186 m_suiteThreadPoolSize, Integer.MAX_VALUE, TimeUnit.MILLISECONDS, 1187 new LinkedBlockingQueue<Runnable>()); 1188 1189 Utils.log("TestNG", 2, "Starting executor for all suites"); 1190 // Run all suites in parallel 1191 pooledExecutor.run(); 1192 try { 1193 pooledExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS); 1194 pooledExecutor.shutdownNow(); 1195 } 1196 catch (InterruptedException handled) { 1197 Thread.currentThread().interrupt(); 1198 error("Error waiting for concurrent executors to finish " + handled.getMessage()); 1199 } 1200 } 1201 } 1202 else { 1203 setStatus(HAS_NO_TEST); 1204 error("No test suite found. Nothing to run"); 1205 usage(); 1206 } 1207 1208 // 1209 // Generate the suites report 1210 // 1211 return Lists.newArrayList(suiteRunnerMap.values()); 1212 } 1213 error(String s)1214 private static void error(String s) { 1215 LOGGER.error(s); 1216 } 1217 1218 /** 1219 * @return the verbose level, checking in order: the verbose level on 1220 * the suite, the verbose level on the TestNG object, or 1. 1221 */ getVerbose(XmlSuite xmlSuite)1222 private int getVerbose(XmlSuite xmlSuite) { 1223 int result = xmlSuite.getVerbose() != null ? xmlSuite.getVerbose() 1224 : (m_verbose != null ? m_verbose : DEFAULT_VERBOSE); 1225 return result; 1226 } 1227 1228 /** 1229 * Recursively runs suites. Runs the children suites before running the parent 1230 * suite. This is done so that the results for parent suite can reflect the 1231 * combined results of the children suites. 1232 * 1233 * @param xmlSuite XML Suite to be executed 1234 * @param suiteRunnerMap Maps {@code XmlSuite}s to respective {@code ISuite} 1235 * @param verbose verbose level 1236 * @param defaultSuiteName default suite name 1237 */ runSuitesSequentially(XmlSuite xmlSuite, SuiteRunnerMap suiteRunnerMap, int verbose, String defaultSuiteName)1238 private void runSuitesSequentially(XmlSuite xmlSuite, 1239 SuiteRunnerMap suiteRunnerMap, int verbose, String defaultSuiteName) { 1240 for (XmlSuite childSuite : xmlSuite.getChildSuites()) { 1241 runSuitesSequentially(childSuite, suiteRunnerMap, verbose, defaultSuiteName); 1242 } 1243 SuiteRunnerWorker srw = new SuiteRunnerWorker(suiteRunnerMap.get(xmlSuite), suiteRunnerMap, 1244 verbose, defaultSuiteName); 1245 srw.run(); 1246 } 1247 1248 /** 1249 * Populates the dynamic graph with the reverse hierarchy of suites. Edges are 1250 * added pointing from child suite runners to parent suite runners, hence making 1251 * parent suite runners dependent on all the child suite runners 1252 * 1253 * @param suiteGraph dynamic graph representing the reverse hierarchy of SuiteRunners 1254 * @param suiteRunnerMap Map with XMLSuite as key and its respective SuiteRunner as value 1255 * @param xmlSuite XML Suite 1256 */ populateSuiteGraph(DynamicGraph<ISuite> suiteGraph , SuiteRunnerMap suiteRunnerMap, XmlSuite xmlSuite)1257 private void populateSuiteGraph(DynamicGraph<ISuite> suiteGraph /* OUT */, 1258 SuiteRunnerMap suiteRunnerMap, XmlSuite xmlSuite) { 1259 ISuite parentSuiteRunner = suiteRunnerMap.get(xmlSuite); 1260 if (xmlSuite.getChildSuites().isEmpty()) { 1261 suiteGraph.addNode(parentSuiteRunner); 1262 } 1263 else { 1264 for (XmlSuite childSuite : xmlSuite.getChildSuites()) { 1265 suiteGraph.addEdge(parentSuiteRunner, suiteRunnerMap.get(childSuite)); 1266 populateSuiteGraph(suiteGraph, suiteRunnerMap, childSuite); 1267 } 1268 } 1269 } 1270 1271 /** 1272 * Creates the {@code SuiteRunner}s and populates the suite runner map with 1273 * this information 1274 * @param suiteRunnerMap Map with XMLSuite as key and it's respective 1275 * SuiteRunner as value. This is updated as part of this method call 1276 * @param xmlSuite Xml Suite (and its children) for which {@code SuiteRunner}s are created 1277 */ createSuiteRunners(SuiteRunnerMap suiteRunnerMap , XmlSuite xmlSuite)1278 private void createSuiteRunners(SuiteRunnerMap suiteRunnerMap /* OUT */, XmlSuite xmlSuite) { 1279 if (null != m_isJUnit && ! m_isJUnit.equals(XmlSuite.DEFAULT_JUNIT)) { 1280 xmlSuite.setJUnit(m_isJUnit); 1281 } 1282 1283 // If the skip flag was invoked on the command line, it 1284 // takes precedence 1285 if (null != m_skipFailedInvocationCounts) { 1286 xmlSuite.setSkipFailedInvocationCounts(m_skipFailedInvocationCounts); 1287 } 1288 1289 // Override the XmlSuite verbose value with the one from TestNG 1290 if (m_verbose != null) { 1291 xmlSuite.setVerbose(m_verbose); 1292 } 1293 1294 if (null != m_configFailurePolicy) { 1295 xmlSuite.setConfigFailurePolicy(m_configFailurePolicy); 1296 } 1297 1298 for (XmlTest t : xmlSuite.getTests()) { 1299 for (Map.Entry<String, Integer> ms : m_methodDescriptors.entrySet()) { 1300 XmlMethodSelector xms = new XmlMethodSelector(); 1301 xms.setName(ms.getKey()); 1302 xms.setPriority(ms.getValue()); 1303 t.getMethodSelectors().add(xms); 1304 } 1305 } 1306 1307 suiteRunnerMap.put(xmlSuite, createSuiteRunner(xmlSuite)); 1308 1309 for (XmlSuite childSuite : xmlSuite.getChildSuites()) { 1310 createSuiteRunners(suiteRunnerMap, childSuite); 1311 } 1312 } 1313 1314 /** 1315 * Creates a suite runner and configures its initial state 1316 * @param xmlSuite 1317 * @return returns the newly created suite runner 1318 */ createSuiteRunner(XmlSuite xmlSuite)1319 private SuiteRunner createSuiteRunner(XmlSuite xmlSuite) { 1320 SuiteRunner result = new SuiteRunner(getConfiguration(), xmlSuite, 1321 m_outputDir, 1322 m_testRunnerFactory, 1323 m_useDefaultListeners, 1324 m_methodInterceptors, 1325 m_invokedMethodListeners, 1326 m_testListeners, 1327 m_classListeners); 1328 1329 for (ISuiteListener isl : m_suiteListeners) { 1330 result.addListener(isl); 1331 } 1332 1333 for (IReporter r : result.getReporters()) { 1334 addListener(r); 1335 } 1336 1337 for (IConfigurationListener cl : m_configuration.getConfigurationListeners()) { 1338 result.addConfigurationListener(cl); 1339 } 1340 1341 return result; 1342 } 1343 getConfiguration()1344 protected IConfiguration getConfiguration() { 1345 return m_configuration; 1346 } 1347 1348 /** 1349 * The TestNG entry point for command line execution. 1350 * 1351 * @param argv the TestNG command line parameters. 1352 * @throws FileNotFoundException 1353 */ main(String[] argv)1354 public static void main(String[] argv) { 1355 TestNG testng = privateMain(argv, null); 1356 System.exit(testng.getStatus()); 1357 } 1358 1359 /** 1360 * <B>Note</B>: this method is not part of the public API and is meant for internal usage only. 1361 */ privateMain(String[] argv, ITestListener listener)1362 public static TestNG privateMain(String[] argv, ITestListener listener) { 1363 TestNG result = new TestNG(); 1364 1365 if (null != listener) { 1366 result.addListener(listener); 1367 } 1368 1369 // 1370 // Parse the arguments 1371 // 1372 try { 1373 CommandLineArgs cla = new CommandLineArgs(); 1374 m_jCommander = new JCommander(cla, argv); 1375 validateCommandLineParameters(cla); 1376 result.configure(cla); 1377 } 1378 catch(ParameterException ex) { 1379 exitWithError(ex.getMessage()); 1380 } 1381 1382 // 1383 // Run 1384 // 1385 try { 1386 result.run(); 1387 } 1388 catch(TestNGException ex) { 1389 if (TestRunner.getVerbose() > 1) { 1390 ex.printStackTrace(System.out); 1391 } 1392 else { 1393 error(ex.getMessage()); 1394 } 1395 result.setStatus(HAS_FAILURE); 1396 } 1397 1398 return result; 1399 } 1400 1401 /** 1402 * Configure the TestNG instance based on the command line parameters. 1403 */ configure(CommandLineArgs cla)1404 protected void configure(CommandLineArgs cla) { 1405 if (cla.verbose != null) { 1406 setVerbose(cla.verbose); 1407 } 1408 setOutputDirectory(cla.outputDirectory); 1409 1410 String testClasses = cla.testClass; 1411 if (null != testClasses) { 1412 String[] strClasses = testClasses.split(","); 1413 List<Class> classes = Lists.newArrayList(); 1414 for (String c : strClasses) { 1415 classes.add(ClassHelper.fileToClass(c)); 1416 } 1417 1418 setTestClasses(classes.toArray(new Class[classes.size()])); 1419 } 1420 1421 setOutputDirectory(cla.outputDirectory); 1422 1423 if (cla.testNames != null) { 1424 setTestNames(Arrays.asList(cla.testNames.split(","))); 1425 } 1426 1427 // List<String> testNgXml = (List<String>) cmdLineArgs.get(CommandLineArgs.SUITE_DEF); 1428 // if (null != testNgXml) { 1429 // setTestSuites(testNgXml); 1430 // } 1431 1432 // Note: can't use a Boolean field here because we are allowing a boolean 1433 // parameter with an arity of 1 ("-usedefaultlisteners false") 1434 if (cla.useDefaultListeners != null) { 1435 setUseDefaultListeners("true".equalsIgnoreCase(cla.useDefaultListeners)); 1436 } 1437 1438 setGroups(cla.groups); 1439 setExcludedGroups(cla.excludedGroups); 1440 setTestJar(cla.testJar); 1441 setXmlPathInJar(cla.xmlPathInJar); 1442 setJUnit(cla.junit); 1443 setMixed(cla.mixed); 1444 setMaster(cla.master); 1445 setSlave(cla.slave); 1446 setSkipFailedInvocationCounts(cla.skipFailedInvocationCounts); 1447 if (cla.parallelMode != null) { 1448 setParallel(cla.parallelMode); 1449 } 1450 if (cla.configFailurePolicy != null) { 1451 setConfigFailurePolicy(cla.configFailurePolicy); 1452 } 1453 if (cla.threadCount != null) { 1454 setThreadCount(cla.threadCount); 1455 } 1456 if (cla.dataProviderThreadCount != null) { 1457 setDataProviderThreadCount(cla.dataProviderThreadCount); 1458 } 1459 if (cla.suiteName != null) { 1460 setDefaultSuiteName(cla.suiteName); 1461 } 1462 if (cla.testName != null) { 1463 setDefaultTestName(cla.testName); 1464 } 1465 if (cla.listener != null) { 1466 String sep = ";"; 1467 if (cla.listener.contains(",")) { 1468 sep = ","; 1469 } 1470 String[] strs = Utils.split(cla.listener, sep); 1471 List<Class> classes = Lists.newArrayList(); 1472 1473 for (String cls : strs) { 1474 classes.add(ClassHelper.fileToClass(cls)); 1475 } 1476 1477 setListenerClasses(classes); 1478 } 1479 1480 if (null != cla.methodSelectors) { 1481 String[] strs = Utils.split(cla.methodSelectors, ","); 1482 for (String cls : strs) { 1483 String[] sel = Utils.split(cls, ":"); 1484 try { 1485 if (sel.length == 2) { 1486 addMethodSelector(sel[0], Integer.parseInt(sel[1])); 1487 } else { 1488 error("Method selector value was not in the format org.example.Selector:4"); 1489 } 1490 } 1491 catch (NumberFormatException nfe) { 1492 error("Method selector value was not in the format org.example.Selector:4"); 1493 } 1494 } 1495 } 1496 1497 if (cla.objectFactory != null) { 1498 setObjectFactory(ClassHelper.fileToClass(cla.objectFactory)); 1499 } 1500 if (cla.testRunnerFactory != null) { 1501 setTestRunnerFactoryClass( 1502 ClassHelper.fileToClass(cla.testRunnerFactory)); 1503 } 1504 1505 if (cla.reporter != null) { 1506 ReporterConfig reporterConfig = ReporterConfig.deserialize(cla.reporter); 1507 addReporter(reporterConfig); 1508 } 1509 1510 if (cla.commandLineMethods.size() > 0) { 1511 m_commandLineMethods = cla.commandLineMethods; 1512 } 1513 1514 if (cla.suiteFiles != null) { 1515 setTestSuites(cla.suiteFiles); 1516 } 1517 1518 setSuiteThreadPoolSize(cla.suiteThreadPoolSize); 1519 setRandomizeSuites(cla.randomizeSuites); 1520 } 1521 setSuiteThreadPoolSize(Integer suiteThreadPoolSize)1522 public void setSuiteThreadPoolSize(Integer suiteThreadPoolSize) { 1523 m_suiteThreadPoolSize = suiteThreadPoolSize; 1524 } 1525 getSuiteThreadPoolSize()1526 public Integer getSuiteThreadPoolSize() { 1527 return m_suiteThreadPoolSize; 1528 } 1529 setRandomizeSuites(boolean randomizeSuites)1530 public void setRandomizeSuites(boolean randomizeSuites) { 1531 m_randomizeSuites = randomizeSuites; 1532 } 1533 1534 /** 1535 * This method is invoked by Maven's Surefire, only remove it once 1536 * Surefire has been modified to no longer call it. 1537 */ setSourcePath(String path)1538 public void setSourcePath(String path) { 1539 // nop 1540 } 1541 1542 /** 1543 * This method is invoked by Maven's Surefire to configure the runner, 1544 * do not remove unless you know for sure that Surefire has been updated 1545 * to use the new configure(CommandLineArgs) method. 1546 * 1547 * @deprecated use new configure(CommandLineArgs) method 1548 */ 1549 @SuppressWarnings({"unchecked"}) 1550 @Deprecated configure(Map cmdLineArgs)1551 public void configure(Map cmdLineArgs) { 1552 CommandLineArgs result = new CommandLineArgs(); 1553 1554 Integer verbose = (Integer) cmdLineArgs.get(CommandLineArgs.LOG); 1555 if (null != verbose) { 1556 result.verbose = verbose; 1557 } 1558 result.outputDirectory = (String) cmdLineArgs.get(CommandLineArgs.OUTPUT_DIRECTORY); 1559 1560 String testClasses = (String) cmdLineArgs.get(CommandLineArgs.TEST_CLASS); 1561 if (null != testClasses) { 1562 result.testClass = testClasses; 1563 } 1564 1565 String testNames = (String) cmdLineArgs.get(CommandLineArgs.TEST_NAMES); 1566 if (testNames != null) { 1567 result.testNames = testNames; 1568 } 1569 1570 String useDefaultListeners = (String) cmdLineArgs.get(CommandLineArgs.USE_DEFAULT_LISTENERS); 1571 if (null != useDefaultListeners) { 1572 result.useDefaultListeners = useDefaultListeners; 1573 } 1574 1575 result.groups = (String) cmdLineArgs.get(CommandLineArgs.GROUPS); 1576 result.excludedGroups = (String) cmdLineArgs.get(CommandLineArgs.EXCLUDED_GROUPS); 1577 result.testJar = (String) cmdLineArgs.get(CommandLineArgs.TEST_JAR); 1578 result.xmlPathInJar = (String) cmdLineArgs.get(CommandLineArgs.XML_PATH_IN_JAR); 1579 result.junit = (Boolean) cmdLineArgs.get(CommandLineArgs.JUNIT); 1580 result.mixed = (Boolean) cmdLineArgs.get(CommandLineArgs.MIXED); 1581 result.master = (String) cmdLineArgs.get(CommandLineArgs.MASTER); 1582 result.slave = (String) cmdLineArgs.get(CommandLineArgs.SLAVE); 1583 result.skipFailedInvocationCounts = (Boolean) cmdLineArgs.get( 1584 CommandLineArgs.SKIP_FAILED_INVOCATION_COUNTS); 1585 String parallelMode = (String) cmdLineArgs.get(CommandLineArgs.PARALLEL); 1586 if (parallelMode != null) { 1587 result.parallelMode = XmlSuite.ParallelMode.getValidParallel(parallelMode); 1588 } 1589 1590 String threadCount = (String) cmdLineArgs.get(CommandLineArgs.THREAD_COUNT); 1591 if (threadCount != null) { 1592 result.threadCount = Integer.parseInt(threadCount); 1593 } 1594 1595 // Not supported by Surefire yet 1596 Integer dptc = (Integer) cmdLineArgs.get(CommandLineArgs.DATA_PROVIDER_THREAD_COUNT); 1597 if (dptc != null) { 1598 result.dataProviderThreadCount = dptc; 1599 } 1600 String defaultSuiteName = (String) cmdLineArgs.get(CommandLineArgs.SUITE_NAME); 1601 if (defaultSuiteName != null) { 1602 result.suiteName = defaultSuiteName; 1603 } 1604 1605 String defaultTestName = (String) cmdLineArgs.get(CommandLineArgs.TEST_NAME); 1606 if (defaultTestName != null) { 1607 result.testName = defaultTestName; 1608 } 1609 1610 Object listeners = cmdLineArgs.get(CommandLineArgs.LISTENER); 1611 if (listeners instanceof List) { 1612 result.listener = Utils.join((List<?>) listeners, ","); 1613 } else { 1614 result.listener = (String) listeners; 1615 } 1616 1617 String ms = (String) cmdLineArgs.get(CommandLineArgs.METHOD_SELECTORS); 1618 if (null != ms) { 1619 result.methodSelectors = ms; 1620 } 1621 1622 String objectFactory = (String) cmdLineArgs.get(CommandLineArgs.OBJECT_FACTORY); 1623 if(null != objectFactory) { 1624 result.objectFactory = objectFactory; 1625 } 1626 1627 String runnerFactory = (String) cmdLineArgs.get(CommandLineArgs.TEST_RUNNER_FACTORY); 1628 if (null != runnerFactory) { 1629 result.testRunnerFactory = runnerFactory; 1630 } 1631 1632 String reporterConfigs = (String) cmdLineArgs.get(CommandLineArgs.REPORTER); 1633 if (reporterConfigs != null) { 1634 result.reporter = reporterConfigs; 1635 } 1636 1637 String failurePolicy = (String)cmdLineArgs.get(CommandLineArgs.CONFIG_FAILURE_POLICY); 1638 if (failurePolicy != null) { 1639 result.configFailurePolicy = failurePolicy; 1640 } 1641 1642 Object suiteThreadPoolSize = cmdLineArgs.get(CommandLineArgs.SUITE_THREAD_POOL_SIZE); 1643 if (null != suiteThreadPoolSize) { 1644 if (suiteThreadPoolSize instanceof String){ 1645 result.suiteThreadPoolSize=Integer.parseInt((String) suiteThreadPoolSize); 1646 } 1647 if (suiteThreadPoolSize instanceof Integer){ 1648 result.suiteThreadPoolSize=(Integer) suiteThreadPoolSize; 1649 } 1650 } 1651 1652 configure(result); 1653 } 1654 1655 /** 1656 * Only run the specified tests from the suite. 1657 */ setTestNames(List<String> testNames)1658 public void setTestNames(List<String> testNames) { 1659 m_testNames = testNames; 1660 } 1661 setSkipFailedInvocationCounts(Boolean skip)1662 public void setSkipFailedInvocationCounts(Boolean skip) { 1663 m_skipFailedInvocationCounts = skip; 1664 } 1665 addReporter(ReporterConfig reporterConfig)1666 private void addReporter(ReporterConfig reporterConfig) { 1667 Object instance = reporterConfig.newReporterInstance(); 1668 if (instance != null) { 1669 addListener(instance); 1670 } else { 1671 LOGGER.warn("Could not find reporte class : " + reporterConfig.getClassName()); 1672 } 1673 } 1674 1675 /** 1676 * Specify if this run should be in Master-Slave mode as Master 1677 * 1678 * @param fileName remote.properties path 1679 */ setMaster(String fileName)1680 public void setMaster(String fileName) { 1681 m_masterfileName = fileName; 1682 } 1683 1684 /** 1685 * Specify if this run should be in Master-Slave mode as slave 1686 * 1687 * @param fileName remote.properties path 1688 */ setSlave(String fileName)1689 public void setSlave(String fileName) { 1690 m_slavefileName = fileName; 1691 } 1692 1693 /** 1694 * Specify if this run should be made in JUnit mode 1695 * 1696 * @param isJUnit 1697 */ setJUnit(Boolean isJUnit)1698 public void setJUnit(Boolean isJUnit) { 1699 m_isJUnit = isJUnit; 1700 } 1701 1702 /** 1703 * Specify if this run should be made in mixed mode 1704 */ setMixed(Boolean isMixed)1705 public void setMixed(Boolean isMixed) { 1706 if(isMixed==null){ 1707 return; 1708 } 1709 m_isMixed = isMixed; 1710 } 1711 1712 /** 1713 * @deprecated The TestNG version is now established at load time. This 1714 * method is not required anymore and is now a no-op. 1715 */ 1716 @Deprecated setTestNGVersion()1717 public static void setTestNGVersion() { 1718 LOGGER.info("setTestNGVersion has been deprecated."); 1719 } 1720 1721 /** 1722 * Returns true if this is the JDK 1.4 JAR version of TestNG, false otherwise. 1723 * 1724 * @return true if this is the JDK 1.4 JAR version of TestNG, false otherwise. 1725 */ 1726 @Deprecated isJdk14()1727 public static boolean isJdk14() { 1728 return false; 1729 } 1730 1731 /** 1732 * Double check that the command line parameters are valid. 1733 */ validateCommandLineParameters(CommandLineArgs args)1734 protected static void validateCommandLineParameters(CommandLineArgs args) { 1735 String testClasses = args.testClass; 1736 List<String> testNgXml = args.suiteFiles; 1737 String testJar = args.testJar; 1738 String slave = args.slave; 1739 List<String> methods = args.commandLineMethods; 1740 1741 if (testClasses == null && slave == null && testJar == null 1742 && (testNgXml == null || testNgXml.isEmpty()) 1743 && (methods == null || methods.isEmpty())) { 1744 throw new ParameterException("You need to specify at least one testng.xml, one class" 1745 + " or one method"); 1746 } 1747 1748 String groups = args.groups; 1749 String excludedGroups = args.excludedGroups; 1750 1751 if (testJar == null && 1752 (null != groups || null != excludedGroups) && testClasses == null 1753 && (testNgXml == null || testNgXml.isEmpty())) { 1754 throw new ParameterException("Groups option should be used with testclass option"); 1755 } 1756 1757 if (args.slave != null && args.master != null) { 1758 throw new ParameterException(CommandLineArgs.SLAVE + " can't be combined with " 1759 + CommandLineArgs.MASTER); 1760 } 1761 1762 Boolean junit = args.junit; 1763 Boolean mixed = args.mixed; 1764 if (junit && mixed) { 1765 throw new ParameterException(CommandLineArgs.MIXED + " can't be combined with " 1766 + CommandLineArgs.JUNIT); 1767 } 1768 } 1769 1770 /** 1771 * @return true if at least one test failed. 1772 */ hasFailure()1773 public boolean hasFailure() { 1774 return (getStatus() & HAS_FAILURE) == HAS_FAILURE; 1775 } 1776 1777 /** 1778 * @return true if at least one test failed within success percentage. 1779 */ hasFailureWithinSuccessPercentage()1780 public boolean hasFailureWithinSuccessPercentage() { 1781 return (getStatus() & HAS_FSP) == HAS_FSP; 1782 } 1783 1784 /** 1785 * @return true if at least one test was skipped. 1786 */ hasSkip()1787 public boolean hasSkip() { 1788 return (getStatus() & HAS_SKIPPED) == HAS_SKIPPED; 1789 } 1790 exitWithError(String msg)1791 static void exitWithError(String msg) { 1792 System.err.println(msg); 1793 usage(); 1794 System.exit(1); 1795 } 1796 getOutputDirectory()1797 public String getOutputDirectory() { 1798 return m_outputDir; 1799 } 1800 getAnnotationTransformer()1801 public IAnnotationTransformer getAnnotationTransformer() { 1802 return m_annotationTransformer; 1803 } 1804 setAnnotationTransformer(IAnnotationTransformer t)1805 public void setAnnotationTransformer(IAnnotationTransformer t) { 1806 // compare by reference! 1807 if (m_annotationTransformer != m_defaultAnnoProcessor && m_annotationTransformer != t) { 1808 LOGGER.warn("AnnotationTransformer already set"); 1809 } 1810 m_annotationTransformer = t; 1811 } 1812 1813 /** 1814 * @return the defaultSuiteName 1815 */ getDefaultSuiteName()1816 public String getDefaultSuiteName() { 1817 return m_defaultSuiteName; 1818 } 1819 1820 /** 1821 * @param defaultSuiteName the defaultSuiteName to set 1822 */ setDefaultSuiteName(String defaultSuiteName)1823 public void setDefaultSuiteName(String defaultSuiteName) { 1824 m_defaultSuiteName = defaultSuiteName; 1825 } 1826 1827 /** 1828 * @return the defaultTestName 1829 */ getDefaultTestName()1830 public String getDefaultTestName() { 1831 return m_defaultTestName; 1832 } 1833 1834 /** 1835 * @param defaultTestName the defaultTestName to set 1836 */ setDefaultTestName(String defaultTestName)1837 public void setDefaultTestName(String defaultTestName) { 1838 m_defaultTestName = defaultTestName; 1839 } 1840 1841 /** 1842 * Sets the policy for whether or not to ever invoke a configuration method again after 1843 * it has failed once. Possible values are defined in {@link XmlSuite}. The default 1844 * value is {@link XmlSuite#SKIP}. 1845 * @param failurePolicy the configuration failure policy 1846 */ setConfigFailurePolicy(String failurePolicy)1847 public void setConfigFailurePolicy(String failurePolicy) { 1848 m_configFailurePolicy = failurePolicy; 1849 } 1850 1851 /** 1852 * Returns the configuration failure policy. 1853 * @return config failure policy 1854 */ getConfigFailurePolicy()1855 public String getConfigFailurePolicy() { 1856 return m_configFailurePolicy; 1857 } 1858 1859 // DEPRECATED: to be removed after a major version change 1860 /** 1861 * @deprecated since 5.1 1862 */ 1863 @Deprecated getDefault()1864 public static TestNG getDefault() { 1865 return m_instance; 1866 } 1867 1868 /** 1869 * @deprecated since 5.1 1870 */ 1871 @Deprecated setHasFailure(boolean hasFailure)1872 public void setHasFailure(boolean hasFailure) { 1873 m_status |= HAS_FAILURE; 1874 } 1875 1876 /** 1877 * @deprecated since 5.1 1878 */ 1879 @Deprecated setHasFailureWithinSuccessPercentage(boolean hasFailureWithinSuccessPercentage)1880 public void setHasFailureWithinSuccessPercentage(boolean hasFailureWithinSuccessPercentage) { 1881 m_status |= HAS_FSP; 1882 } 1883 1884 /** 1885 * @deprecated since 5.1 1886 */ 1887 @Deprecated setHasSkip(boolean hasSkip)1888 public void setHasSkip(boolean hasSkip) { 1889 m_status |= HAS_SKIPPED; 1890 } 1891 1892 public static class ExitCodeListener implements IResultListener2 { 1893 private TestNG m_mainRunner; 1894 ExitCodeListener()1895 public ExitCodeListener() { 1896 m_mainRunner = TestNG.m_instance; 1897 } 1898 ExitCodeListener(TestNG runner)1899 public ExitCodeListener(TestNG runner) { 1900 m_mainRunner = runner; 1901 } 1902 1903 @Override beforeConfiguration(ITestResult tr)1904 public void beforeConfiguration(ITestResult tr) { 1905 } 1906 1907 @Override onTestFailure(ITestResult result)1908 public void onTestFailure(ITestResult result) { 1909 setHasRunTests(); 1910 m_mainRunner.setStatus(HAS_FAILURE); 1911 } 1912 1913 @Override onTestSkipped(ITestResult result)1914 public void onTestSkipped(ITestResult result) { 1915 setHasRunTests(); 1916 if ((m_mainRunner.getStatus() & HAS_FAILURE) != 0) { 1917 m_mainRunner.setStatus(HAS_SKIPPED); 1918 } 1919 } 1920 1921 @Override onTestFailedButWithinSuccessPercentage(ITestResult result)1922 public void onTestFailedButWithinSuccessPercentage(ITestResult result) { 1923 setHasRunTests(); 1924 m_mainRunner.setStatus(HAS_FSP); 1925 } 1926 1927 @Override onTestSuccess(ITestResult result)1928 public void onTestSuccess(ITestResult result) { 1929 setHasRunTests(); 1930 } 1931 1932 @Override onStart(ITestContext context)1933 public void onStart(ITestContext context) { 1934 setHasRunTests(); 1935 } 1936 1937 @Override onFinish(ITestContext context)1938 public void onFinish(ITestContext context) { 1939 } 1940 1941 @Override onTestStart(ITestResult result)1942 public void onTestStart(ITestResult result) { 1943 setHasRunTests(); 1944 } 1945 setHasRunTests()1946 private void setHasRunTests() { 1947 m_mainRunner.m_hasTests= true; 1948 } 1949 1950 /** 1951 * @see org.testng.IConfigurationListener#onConfigurationFailure(org.testng.ITestResult) 1952 */ 1953 @Override onConfigurationFailure(ITestResult itr)1954 public void onConfigurationFailure(ITestResult itr) { 1955 m_mainRunner.setStatus(HAS_FAILURE); 1956 } 1957 1958 /** 1959 * @see org.testng.IConfigurationListener#onConfigurationSkip(org.testng.ITestResult) 1960 */ 1961 @Override onConfigurationSkip(ITestResult itr)1962 public void onConfigurationSkip(ITestResult itr) { 1963 m_mainRunner.setStatus(HAS_SKIPPED); 1964 } 1965 1966 /** 1967 * @see org.testng.IConfigurationListener#onConfigurationSuccess(org.testng.ITestResult) 1968 */ 1969 @Override onConfigurationSuccess(ITestResult itr)1970 public void onConfigurationSuccess(ITestResult itr) { 1971 } 1972 } 1973 setConfigurable(IConfigurable c)1974 private void setConfigurable(IConfigurable c) { 1975 // compare by reference! 1976 if (m_configurable != null && m_configurable != c) { 1977 LOGGER.warn("Configurable already set"); 1978 } 1979 m_configurable = c; 1980 } 1981 setHookable(IHookable h)1982 private void setHookable(IHookable h) { 1983 // compare by reference! 1984 if (m_hookable != null && m_hookable != h) { 1985 LOGGER.warn("Hookable already set"); 1986 } 1987 m_hookable = h; 1988 } 1989 setMethodInterceptor(IMethodInterceptor methodInterceptor)1990 public void setMethodInterceptor(IMethodInterceptor methodInterceptor) { 1991 m_methodInterceptors.add(methodInterceptor); 1992 } 1993 setDataProviderThreadCount(int count)1994 public void setDataProviderThreadCount(int count) { 1995 m_dataProviderThreadCount = count; 1996 } 1997 1998 /** Add a class loader to the searchable loaders. */ addClassLoader(final ClassLoader loader)1999 public void addClassLoader(final ClassLoader loader) { 2000 if (loader != null) { 2001 ClassHelper.addClassLoader(loader); 2002 } 2003 } 2004 setPreserveOrder(boolean b)2005 public void setPreserveOrder(boolean b) { 2006 m_preserveOrder = b; 2007 } 2008 getStart()2009 protected long getStart() { 2010 return m_start; 2011 } 2012 getEnd()2013 protected long getEnd() { 2014 return m_end; 2015 } 2016 setGroupByInstances(boolean b)2017 public void setGroupByInstances(boolean b) { 2018 m_groupByInstances = b; 2019 } 2020 2021 ///// 2022 // ServiceLoader testing 2023 // 2024 2025 private URLClassLoader m_serviceLoaderClassLoader; 2026 private List<ITestNGListener> m_serviceLoaderListeners = Lists.newArrayList(); 2027 2028 /* 2029 * Used to test ServiceClassLoader 2030 */ setServiceLoaderClassLoader(URLClassLoader ucl)2031 public void setServiceLoaderClassLoader(URLClassLoader ucl) { 2032 m_serviceLoaderClassLoader = ucl; 2033 } 2034 2035 /* 2036 * Used to test ServiceClassLoader 2037 */ addServiceLoaderListener(ITestNGListener l)2038 private void addServiceLoaderListener(ITestNGListener l) { 2039 m_serviceLoaderListeners.add(l); 2040 } 2041 2042 /* 2043 * Used to test ServiceClassLoader 2044 */ getServiceLoaderListeners()2045 public List<ITestNGListener> getServiceLoaderListeners() { 2046 return m_serviceLoaderListeners; 2047 } 2048 2049 // 2050 // ServiceLoader testing 2051 ///// 2052 } 2053