...44import org.testng.reporters.XMLReporter;45import org.testng.reporters.jq.Main;46import org.testng.util.Strings;47import org.testng.xml.IPostProcessor;48import org.testng.xml.Parser;49import org.testng.xml.XmlClass;50import org.testng.xml.XmlInclude;51import org.testng.xml.XmlMethodSelector;52import org.testng.xml.XmlSuite;53import org.testng.xml.XmlTest;54import com.beust.jcommander.JCommander;55import com.beust.jcommander.ParameterException;56import org.testng.xml.internal.TestNamesMatcher;57import org.testng.xml.internal.XmlSuiteUtils;58import static org.testng.internal.Utils.defaultIfStringEmpty;59import static org.testng.internal.Utils.isStringEmpty;60import static org.testng.internal.Utils.isStringNotEmpty;61import static org.testng.xml.XmlSuite.ParallelMode.skipDeprecatedValues;62/**63 * This class is the main entry point for running tests in the TestNG framework. Users can create64 * their own TestNG object and invoke it in many different ways:65 *66 * <ul>67 * <li>On an existing testng.xml68 * <li>On a synthetic testng.xml, created entirely from Java69 * <li>By directly setting the test classes70 * </ul>71 *72 * You can also define which groups to include or exclude, assign parameters, etc...73 *74 * <p>The command line parameters are:75 *76 * <UL>77 * <LI>-d <TT>outputdir</TT>: specify the output directory78 * <LI>-testclass <TT>class_name</TT>: specifies one or several class names79 * <LI>-testjar <TT>jar_name</TT>: specifies the jar containing the tests80 * <LI>-sourcedir <TT>src1;src2</TT>: ; separated list of source directories (used only when81 * javadoc annotations are used)82 * <LI>-target83 * <LI>-groups84 * <LI>-testrunfactory85 * <LI>-listener86 * </UL>87 *88 * <p>Please consult documentation for more details.89 *90 * <p>FIXME: should support more than simple paths for suite xmls91 *92 * @see #usage()93 * @author <a href = "mailto:cedric@beust.com">Cedric Beust</a>94 */95public class TestNG {96 /** This class' log4testng Logger. */97 private static final Logger LOGGER = Logger.getLogger(TestNG.class);98 /** The default name for a suite launched from the command line */99 public static final String DEFAULT_COMMAND_LINE_SUITE_NAME = "Command line suite";100 /** The default name for a test launched from the command line */101 public static final String DEFAULT_COMMAND_LINE_TEST_NAME = "Command line test";102 /** The default name of the result's output directory (keep public, used by Eclipse). */103 public static final String DEFAULT_OUTPUTDIR = "test-output";104 private static TestNG m_instance;105 private static JCommander m_jCommander;106 private List<String> m_commandLineMethods;107 protected List<XmlSuite> m_suites = Lists.newArrayList();108 private List<XmlSuite> m_cmdlineSuites;109 private String m_outputDir = DEFAULT_OUTPUTDIR;110 private String[] m_includedGroups;111 private String[] m_excludedGroups;112 private Boolean m_isJUnit = XmlSuite.DEFAULT_JUNIT;113 private Boolean m_isMixed = XmlSuite.DEFAULT_MIXED;114 protected boolean m_useDefaultListeners = true;115 private ITestRunnerFactory m_testRunnerFactory;116 // These listeners can be overridden from the command line117 private final Map<Class<? extends IClassListener>, IClassListener> m_classListeners =118 Maps.newHashMap();119 private final Map<Class<? extends ITestListener>, ITestListener> m_testListeners =120 Maps.newHashMap();121 private final Map<Class<? extends ISuiteListener>, ISuiteListener> m_suiteListeners =122 Maps.newHashMap();123 private final Map<Class<? extends IReporter>, IReporter> m_reporters = Maps.newHashMap();124 private final Map<Class<? extends IDataProviderListener>, IDataProviderListener>125 m_dataProviderListeners = Maps.newHashMap();126 public static final Integer DEFAULT_VERBOSE = 1;127 // Command line suite parameters128 private int m_threadCount = -1;129 private XmlSuite.ParallelMode m_parallelMode = null;130 private XmlSuite.FailurePolicy m_configFailurePolicy;131 private Class[] m_commandLineTestClasses;132 private String m_defaultSuiteName = DEFAULT_COMMAND_LINE_SUITE_NAME;133 private String m_defaultTestName = DEFAULT_COMMAND_LINE_TEST_NAME;134 private Map<String, Integer> m_methodDescriptors = Maps.newHashMap();135 private Set<XmlMethodSelector> m_selectors = Sets.newLinkedHashSet();136 private ITestObjectFactory m_objectFactory;137 private final Map<Class<? extends IInvokedMethodListener>, IInvokedMethodListener>138 m_invokedMethodListeners = Maps.newHashMap();139 private Integer m_dataProviderThreadCount = null;140 private String m_jarPath;141 /** The path of the testng.xml file inside the jar file */142 private String m_xmlPathInJar = CommandLineArgs.XML_PATH_IN_JAR_DEFAULT;143 private List<String> m_stringSuites = Lists.newArrayList();144 private IHookable m_hookable;145 private IConfigurable m_configurable;146 protected long m_end;147 protected long m_start;148 private final Map<Class<? extends IAlterSuiteListener>, IAlterSuiteListener>149 m_alterSuiteListeners = Maps.newHashMap();150 private boolean m_isInitialized = false;151 private boolean isSuiteInitialized = false;152 private final org.testng.internal.ExitCodeListener exitCodeListener =153 new org.testng.internal.ExitCodeListener();154 private ExitCode exitCode;155 private final Map<Class<? extends IExecutionVisualiser>, IExecutionVisualiser>156 m_executionVisualisers = Maps.newHashMap();157 /** Default constructor. Setting also usage of default listeners/reporters. */158 public TestNG() {159 init(true);160 }161 /**162 * Used by maven2 to have 0 output of any kind come out of testng.163 *164 * @param useDefaultListeners Whether or not any default reports should be added to tests.165 */166 public TestNG(boolean useDefaultListeners) {167 init(useDefaultListeners);168 }169 private void init(boolean useDefaultListeners) {170 m_instance = this;171 m_useDefaultListeners = useDefaultListeners;172 m_configuration = new Configuration();173 }174 public int getStatus() {175 if (exitCodeListener.noTestsFound()) {176 return ExitCode.HAS_NO_TEST;177 }178 return exitCode.getExitCode();179 }180 /**181 * Sets the output directory where the reports will be created.182 *183 * @param outputdir The directory.184 */185 public void setOutputDirectory(final String outputdir) {186 if (isStringNotEmpty(outputdir)) {187 m_outputDir = outputdir;188 }189 }190 /**191 * If this method is passed true before run(), the default listeners will not be used.192 *193 * <ul>194 * <li>org.testng.reporters.TestHTMLReporter195 * <li>org.testng.reporters.JUnitXMLReporter196 * <li>org.testng.reporters.XMLReporter197 * </ul>198 *199 * @see org.testng.reporters.TestHTMLReporter200 * @see org.testng.reporters.JUnitXMLReporter201 * @see org.testng.reporters.XMLReporter202 */203 public void setUseDefaultListeners(boolean useDefaultListeners) {204 m_useDefaultListeners = useDefaultListeners;205 }206 /**207 * Sets a jar containing a testng.xml file.208 *209 * @param jarPath210 */211 public void setTestJar(String jarPath) {212 m_jarPath = jarPath;213 }214 /** Sets the path to the XML file in the test jar file. */215 public void setXmlPathInJar(String xmlPathInJar) {216 m_xmlPathInJar = xmlPathInJar;217 }218 private void parseSuiteFiles() {219 IPostProcessor processor = getProcessor();220 for (XmlSuite s : m_suites) {221 if (s.isParsed()) {222 continue;223 }224 for (String suiteFile : s.getSuiteFiles()) {225 try {226 String fileNameToUse = s.getFileName();227 if (fileNameToUse == null || fileNameToUse.trim().isEmpty()) {228 fileNameToUse = suiteFile;229 }230 Collection<XmlSuite> childSuites = Parser.parse(fileNameToUse, processor);231 for (XmlSuite cSuite : childSuites) {232 cSuite.setParentSuite(s);233 s.getChildSuites().add(cSuite);234 }235 } catch (IOException e) {236 e.printStackTrace(System.out);237 }238 }239 }240 }241 private OverrideProcessor getProcessor() {242 return new OverrideProcessor(m_includedGroups, m_excludedGroups);243 }244 private void parseSuite(String suitePath) {245 if (LOGGER.isDebugEnabled()) {246 LOGGER.debug("suiteXmlPath: \"" + suitePath + "\"");247 }248 try {249 Collection<XmlSuite> allSuites = Parser.parse(suitePath, getProcessor());250 for (XmlSuite s : allSuites) {251 if (this.m_parallelMode != null) {252 s.setParallel(this.m_parallelMode);253 }254 if (this.m_threadCount > 0) {255 s.setThreadCount(this.m_threadCount);256 }257 if (m_testNames == null) {258 m_suites.add(s);259 continue;260 }261 // If test names were specified, only run these test names262 TestNamesMatcher testNamesMatcher = new TestNamesMatcher(s, m_testNames);263 List<String> missMatchedTestname = testNamesMatcher.getMissMatchedTestNames();...