| package org.testng; |
| |
| |
| import java.io.BufferedReader; |
| import java.io.FileReader; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.StringTokenizer; |
| |
| import org.testng.internal.AnnotationTypeEnum; |
| import org.testng.internal.ClassHelper; |
| import org.testng.internal.Utils; |
| import org.testng.internal.version.VersionInfo; |
| import org.testng.log4testng.Logger; |
| |
| /** |
| * TestNG/RemoteTestNG command line arguments parser. |
| * |
| * @author Cedric Beust |
| * @author <a href = "mailto:the_mindstorm@evolva.ro">Alexandru Popescu</a> |
| */ |
| public final class TestNGCommandLineArgs { |
| /** This class's log4testng Logger. */ |
| private static final Logger LOGGER = Logger.getLogger(TestNGCommandLineArgs.class); |
| |
| public static final String SHOW_TESTNG_STACK_FRAMES = "testng.show.stack.frames"; |
| public static final String TEST_CLASSPATH = "testng.test.classpath"; |
| |
| /** The test report output directory option. */ |
| public static final String OUTDIR_COMMAND_OPT = "-d"; |
| |
| /** The list of test classes option. */ |
| public static final String TESTCLASS_COMMAND_OPT = "-testclass"; |
| |
| /** */ |
| public static final String TESTJAR_COMMAND_OPT = "-testjar"; |
| |
| /** The source directory option (when using JavaDoc type annotations). */ |
| public static final String SRC_COMMAND_OPT = "-sourcedir"; |
| |
| // These next two are used by the Eclipse plug-in |
| public static final String PORT_COMMAND_OPT = "-port"; |
| public static final String HOST_COMMAND_OPT = "-host"; |
| |
| /** The logging level option. */ |
| public static final String LOG = "-log"; |
| |
| /** @deprecated replaced by DEFAULT_ANNOTATIONS_COMMAND_OPT. */ |
| public static final String TARGET_COMMAND_OPT = "-target"; |
| |
| /** The default annotations option (useful in TestNG 15 only). */ |
| public static final String ANNOTATIONS_COMMAND_OPT = "-annotations"; |
| |
| public static final String GROUPS_COMMAND_OPT = "-groups"; |
| public static final String EXCLUDED_GROUPS_COMMAND_OPT = "-excludegroups"; |
| public static final String TESTRUNNER_FACTORY_COMMAND_OPT = "-testrunfactory"; |
| public static final String LISTENER_COMMAND_OPT = "-listener"; |
| public static final String SUITE_DEF_OPT = "testng.suite.definitions"; |
| public static final String JUNIT_DEF_OPT = "-junit"; |
| public static final String SLAVE_OPT = "-slave"; |
| public static final String HOSTFILE_OPT = "-hostfile"; |
| public static final String THREAD_COUNT = "-threadcount"; |
| public static final String USE_DEFAULT_LISTENERS = "-usedefaultlisteners"; |
| public static final String PARALLEL_MODE = "-parallel"; |
| public static final String SUITE_NAME_OPT = "-suitename"; |
| public static final String TEST_NAME_OPT = "-testname"; |
| |
| /** |
| * When given a file name to form a class name, the file name is parsed and divided |
| * into segments. For example, "c:/java/classes/com/foo/A.class" would be divided |
| * into 6 segments {"C:" "java", "classes", "com", "foo", "A"}. The first segment |
| * actually making up the class name is [3]. This value is saved in m_lastGoodRootIndex |
| * so that when we parse the next file name, we will try 3 right away. If 3 fails we |
| * will take the long approach. This is just a optimization cache value. |
| */ |
| private static int m_lastGoodRootIndex = -1; |
| |
| /** |
| * Hide the constructor for utility class. |
| */ |
| private TestNGCommandLineArgs() { |
| // Hide constructor for utility class |
| } |
| |
| /** |
| * Parses the command line options and returns a map from option string to parsed values. |
| * For example, if argv contains {..., "-sourcedir", "src/main", "-target", ...} then |
| * the map would contain an entry in which the key would be the "-sourcedir" String and |
| * the value would be the "src/main" String. |
| * |
| * @param originalArgv the command line options. |
| * @return the parsed parameters as a map from option string to parsed values. |
| */ |
| public static Map parseCommandLine(final String[] originalArgv) { |
| for (int i = 0; i < originalArgv.length; ++i) { |
| LOGGER.debug("originalArgv[" + i + "] = \"" + originalArgv[i] + "\""); |
| } |
| // TODO CQ In this method, is this OK to simply ignore invalid parameters? |
| LOGGER.debug("TestNG version: \"" + (VersionInfo.IS_JDK14 ? "14" : "15") + "\""); |
| |
| Map<String, Object> arguments = new HashMap<String, Object>(); |
| String[] argv = expandArgv(originalArgv); |
| |
| for (int i = 0; i < argv.length; i++) { |
| if (OUTDIR_COMMAND_OPT.equalsIgnoreCase(argv[i])) { |
| if ((i + 1) < argv.length) { |
| arguments.put(OUTDIR_COMMAND_OPT, argv[i + 1].trim()); |
| } |
| else { |
| LOGGER.error("WARNING: missing output directory after -d. ignored"); |
| } |
| i++; |
| } |
| else if (GROUPS_COMMAND_OPT.equalsIgnoreCase(argv[i]) |
| || EXCLUDED_GROUPS_COMMAND_OPT.equalsIgnoreCase(argv[i])) { |
| if ((i + 1) < argv.length) { |
| String option = null; |
| if (argv[i + 1].startsWith("\"")) { |
| if (argv[i + 1].endsWith("\"")) { |
| option = argv[i + 1].substring(1, argv[i + 1].length() - 1); |
| } |
| else { |
| LOGGER.error("WARNING: groups option is not well quoted:" + argv[i + 1]); |
| option = argv[i + 1].substring(1); |
| } |
| } |
| else { |
| option = argv[i + 1]; |
| } |
| |
| String opt = GROUPS_COMMAND_OPT.equalsIgnoreCase(argv[i]) |
| ? GROUPS_COMMAND_OPT : EXCLUDED_GROUPS_COMMAND_OPT; |
| arguments.put(opt, option); |
| } |
| else { |
| LOGGER.error("WARNING: missing groups parameter after -groups. ignored"); |
| } |
| i++; |
| } |
| else if (LOG.equalsIgnoreCase(argv[i])) { |
| if ((i + 1) < argv.length) { |
| arguments.put(LOG, Integer.valueOf(argv[i + 1].trim())); |
| } |
| else { |
| LOGGER.error("WARNING: missing log level after -log. ignored"); |
| } |
| i++; |
| } |
| else if (JUNIT_DEF_OPT.equalsIgnoreCase(argv[i])) { |
| arguments.put(JUNIT_DEF_OPT, Boolean.TRUE); |
| } |
| else if (TARGET_COMMAND_OPT.equalsIgnoreCase(argv[i])) { |
| if ((i + 1) < argv.length) { |
| arguments.put(ANNOTATIONS_COMMAND_OPT, AnnotationTypeEnum.valueOf(argv[i + 1])); |
| LOGGER.warn("The usage of " + TARGET_COMMAND_OPT + " has been deprecated. Please use " + ANNOTATIONS_COMMAND_OPT + " instead."); |
| ++i; |
| } |
| } |
| else if (ANNOTATIONS_COMMAND_OPT.equalsIgnoreCase(argv[i])) { |
| if ((i + 1) < argv.length) { |
| arguments.put(ANNOTATIONS_COMMAND_OPT, AnnotationTypeEnum.valueOf(argv[i + 1])); |
| ++i; |
| } |
| } |
| else if (TESTRUNNER_FACTORY_COMMAND_OPT.equalsIgnoreCase(argv[i])) { |
| if ((i + 1) < argv.length) { |
| arguments.put(TESTRUNNER_FACTORY_COMMAND_OPT, fileToClass(argv[++i])); |
| } |
| else { |
| LOGGER.error("WARNING: missing ITestRunnerFactory class or file argument after " |
| + TESTRUNNER_FACTORY_COMMAND_OPT); |
| } |
| } |
| else if (LISTENER_COMMAND_OPT.equalsIgnoreCase(argv[i])) { |
| if ((i + 1) < argv.length) { |
| String[] strs = Utils.split(argv[++i], ";"); |
| List<Class> classes = new ArrayList<Class>(); |
| |
| for (String cls : strs) { |
| classes.add(fileToClass(cls)); |
| } |
| |
| arguments.put(LISTENER_COMMAND_OPT, classes); |
| } |
| else { |
| LOGGER.error("WARNING: missing ITestListener class/file list argument after " |
| + LISTENER_COMMAND_OPT); |
| } |
| } |
| else if (TESTCLASS_COMMAND_OPT.equalsIgnoreCase(argv[i])) { |
| if ((i + 1) < argv.length) { |
| while ((i + 1) < argv.length) { |
| String nextArg = argv[i + 1].trim(); |
| if (!nextArg.toLowerCase().endsWith(".xml") && !nextArg.startsWith("-")) { |
| |
| // Assume it's a class name |
| List<Class> l = (List<Class>) arguments.get(TESTCLASS_COMMAND_OPT); |
| if (null == l) { |
| l = new ArrayList<Class>(); |
| arguments.put(TESTCLASS_COMMAND_OPT, l); |
| } |
| Class cls = fileToClass(nextArg); |
| if (null != cls) { |
| l.add(cls); |
| } |
| |
| i++; |
| } // if |
| else { |
| break; |
| } |
| } |
| } |
| else { |
| TestNG.exitWithError("-testclass must be followed by a classname"); |
| } |
| } |
| else if (TESTJAR_COMMAND_OPT.equalsIgnoreCase(argv[i])) { |
| if ((i + 1) < argv.length) { |
| arguments.put(TESTJAR_COMMAND_OPT, argv[i + 1].trim()); |
| } |
| else { |
| TestNG.exitWithError("-testjar must be followed by a valid jar"); |
| } |
| i++; |
| } |
| else if (SRC_COMMAND_OPT.equalsIgnoreCase(argv[i])) { |
| if ((i + 1) < argv.length) { |
| arguments.put(SRC_COMMAND_OPT, argv[i + 1].trim()); |
| } |
| else { |
| TestNG.exitWithError(SRC_COMMAND_OPT + " must be followed by a directory path"); |
| } |
| i++; |
| } |
| else if (HOST_COMMAND_OPT.equals(argv[i])) { |
| String hostAddress = "127.0.0.1"; |
| if ((i + 1) < argv.length) { |
| hostAddress = argv[i + 1].trim(); |
| i++; |
| } |
| else { |
| LOGGER.warn("WARNING: " |
| + HOST_COMMAND_OPT |
| + " option should be followed by the host address. " |
| + "Using default localhost."); |
| } |
| |
| arguments.put(HOST_COMMAND_OPT, hostAddress); |
| |
| } |
| else if (PORT_COMMAND_OPT.equals(argv[i])) { |
| String portNumber = null; |
| if ((i + 1) < argv.length) { |
| portNumber = argv[i + 1].trim(); |
| } |
| else { |
| TestNG.exitWithError( |
| PORT_COMMAND_OPT + " option should be followed by a valid port number."); |
| } |
| |
| arguments.put(PORT_COMMAND_OPT, portNumber); |
| i++; |
| } |
| else if (SLAVE_OPT.equals(argv[i])) { |
| String clientPortNumber = null; |
| if ((i + 1) < argv.length) { |
| clientPortNumber = argv[i + 1].trim(); |
| } |
| else { |
| TestNG.exitWithError(SLAVE_OPT + " option should be followed by a valid port number."); |
| } |
| |
| arguments.put(SLAVE_OPT, clientPortNumber); |
| i++; |
| } |
| else if (HOSTFILE_OPT.equals(argv[i])) { |
| String hostFile = null; |
| if ((i + 1) < argv.length) { |
| hostFile = argv[i + 1].trim(); |
| } |
| else { |
| TestNG.exitWithError(HOSTFILE_OPT + " option should be followed by the name of a file."); |
| } |
| |
| arguments.put(HOSTFILE_OPT, hostFile); |
| i++; |
| } |
| else if (PARALLEL_MODE.equalsIgnoreCase(argv[i])) { |
| if ((i + 1) < argv.length) { |
| arguments.put(PARALLEL_MODE, argv[i + 1]); |
| i++; |
| } |
| } |
| else if (THREAD_COUNT.equalsIgnoreCase(argv[i])) { |
| if ((i + 1) < argv.length) { |
| arguments.put(THREAD_COUNT, argv[i + 1]); |
| i++; |
| } |
| } |
| else if (USE_DEFAULT_LISTENERS.equalsIgnoreCase(argv[i])) { |
| if ((i + 1) < argv.length) { |
| arguments.put(USE_DEFAULT_LISTENERS, argv[i + 1]); |
| i++; |
| } |
| } |
| else if (SUITE_NAME_OPT.equalsIgnoreCase(argv[i])) { |
| if ((i + 1) < argv.length) { |
| arguments.put(SUITE_NAME_OPT, trim(argv[i + 1])); |
| i++; |
| } |
| } |
| else if (TEST_NAME_OPT.equalsIgnoreCase(argv[i])) { |
| if ((i + 1) < argv.length) { |
| arguments.put(TEST_NAME_OPT, trim(argv[i + 1])); |
| i++; |
| } |
| } |
| // |
| // Unknown option |
| // |
| else if (argv[i].startsWith("-")) { |
| TestNG.exitWithError("Unknown option: " + argv[i]); |
| } |
| // |
| // The XML files |
| // |
| else { |
| List<String> suiteDefs = new ArrayList<String>(); |
| |
| for (int k = i; k < argv.length; k++) { |
| String file = argv[k].trim(); |
| if (file.toLowerCase().endsWith(".xml")) { |
| suiteDefs.add(file); |
| i++; |
| } |
| } |
| |
| arguments.put(SUITE_DEF_OPT, suiteDefs); |
| } |
| } |
| |
| for (Map.Entry entry : arguments.entrySet()) { |
| LOGGER.debug("parseCommandLine argument: \"" |
| + entry.getKey() + "\" = \"" + entry.getValue() + "\""); |
| } |
| return arguments; |
| } |
| |
| |
| /** |
| * @param string |
| * @return |
| */ |
| private static String trim(String string) { |
| String trimSpaces=string.trim(); |
| if (trimSpaces.startsWith("\"")) { |
| if (trimSpaces.endsWith("\"")) { |
| return trimSpaces.substring(1, trimSpaces.length() - 1); |
| } else { |
| return trimSpaces.substring(1); |
| } |
| } else { |
| return trimSpaces; |
| } |
| |
| } |
| |
| /** |
| * Expand the command line parameters to take @ parameters into account. |
| * When @ is encountered, the content of the file that follows is inserted |
| * in the command line |
| * @param originalArgv the original command line parameters |
| * @return the new and enriched command line parameters |
| */ |
| private static String[] expandArgv(String[] originalArgv) {
|
| List<String> vResult = new ArrayList<String>();
|
|
|
| for (String arg : originalArgv) {
|
|
|
| if (arg.startsWith("@")) {
|
| String fileName = arg.substring(1); |
| vResult.addAll(readFile(fileName));
|
| }
|
| else {
|
| vResult.add(arg);
|
| }
|
| }
|
|
|
| return vResult.toArray(new String[vResult.size()]);
|
| } |
| |
| |
| /** |
| * Break a line of parameters into individual parameters as the command line parsing |
| * would do. The line is assumed to contain only un-escaped double quotes. For example |
| * the following Java string: |
| * " a \"command\"\"line\" \"with quotes\" a command line\" with quotes \"here there" |
| * would yield the following 7 tokens: |
| * a,commandline,with quotes,a,command,line with quotes here,there |
| * @param line the command line parameter to be parsed |
| * @return the list of individual command line tokens |
| */ |
| private static List<String> parseArgs(String line) { |
| LOGGER.debug("parseArgs line: \"" + line + "\""); |
| final String SPACE = " "; |
| final String DOUBLE_QUOTE = "\""; |
| |
| // If line contains no double quotes, the space character is the only |
| // separator. Easy to do return quickly (logic is also easier to follow) |
| if (line.indexOf(DOUBLE_QUOTE) == -1) { |
| List<String> results = Arrays.asList(line.split(SPACE)); |
| for (String result : results) { |
| LOGGER.debug("parseArgs result: \"" + result + "\""); |
| } |
| return results; |
| } |
| |
| // TODO There must be an easier way to do this with a regular expression. |
| |
| StringTokenizer st = new StringTokenizer(line, SPACE + DOUBLE_QUOTE, true); |
| List<String> results = new ArrayList<String>(); |
| |
| /** |
| * isInDoubleQuote toggles from false to true when we reach a double |
| * quoted string and toggles back to false when we exit. We need to |
| * know if we are in a double quoted string to treat blanks as normal |
| * characters. Out of quotes blanks separate arguments. |
| * |
| * The following example shows these toggle points: |
| * |
| * " a \"command\"\"line\" \"with quotes\" a command line\" with quotes \"here there" |
| * T F T F T F T F |
| * |
| * If the double quotes are not evenly matched, an exception is thrown. |
| */ |
| boolean isInDoubleQuote = false; |
| |
| /** |
| * isInArg toggles from false to true when we enter a command line argument |
| * and toggles back to false when we exit. The logic is that we toggle to |
| * true at the first non-whitespace character met. We toggle back to false |
| * at first whitespace character not in double quotes or at end of line. |
| * |
| * The following example shows these toggle points: |
| * |
| * " a \"command\"\"line\" \"with quotes\" a command line\" with quotes \"here there" |
| * TF T F T F TFT FT F |
| */ |
| boolean isInArg = false; |
| |
| /** arg is a string buffer to create the argument by concatenating all tokens |
| * that compose it. |
| * |
| * The following example shows the token returned by the parser and the |
| * (spaces, double quotes, others) and resultant argument: |
| * |
| * Input (argument): |
| * "line\" with quotes \"here" |
| * |
| * Tokens (9): |
| * line,", ,with, ,quote, ,",here |
| */ |
| StringBuffer arg = new StringBuffer(); |
| |
| while (st.hasMoreTokens()) { |
| String token = st.nextToken(); |
| |
| if (token.equals(SPACE)) { |
| if (isInArg) { |
| if (isInDoubleQuote) { |
| // Spaces within double quotes are treated as normal spaces |
| arg.append(SPACE); |
| } |
| else { |
| // First spaces outside double quotes marks the end of the argument. |
| isInArg = false; |
| results.add(arg.toString()); |
| arg = new StringBuffer(); |
| } |
| } |
| } |
| else if (token.equals(DOUBLE_QUOTE)) { |
| // If we encounter a double quote, we may be entering a new argument |
| // (isInArg is false) or continuing the current argument (isInArg is true). |
| isInArg = true; |
| isInDoubleQuote = !isInDoubleQuote; |
| } |
| else { |
| // We we encounter a new token, we may be entering a new argument |
| // (isInArg is false) or continuing the current argument (isInArg is true). |
| isInArg = true; |
| arg.append(token); |
| } |
| } |
| |
| // In some (most) cases we exit this parsing because there are no tokens left |
| // but we have not encountered a token to indicate that the last argument has |
| // completely been read. For example, if the command line ends with a whitespace |
| // the isInArg will toggle to false and the argument will be completely read. |
| if (isInArg) { |
| // End of last argument |
| results.add(arg.toString()); |
| } |
| |
| // If we exit the parsing of the command line with an uneven number of double |
| // quotes, throw an exception. |
| if (isInDoubleQuote) { |
| throw new IllegalArgumentException("Unbalanced double quotes: \"" + line + "\""); |
| } |
| |
| for (String result : results) { |
| LOGGER.debug("parseArgs result: \"" + result + "\""); |
| } |
| |
| return results; |
| } |
| |
| /** |
| * Reads the file specified by filename and returns the file content as a string. |
| * End of lines are replaced by a space |
| * |
| * @param fileName the command line filename |
| * @return the file content as a string. |
| */ |
| public static List<String> readFile(String fileName) {
|
| List<String> result = new ArrayList<String>();
|
|
|
| try {
|
| BufferedReader bufRead = new BufferedReader(new FileReader(fileName));
|
|
|
| String line;
|
|
|
| // Read through file one line at time. Print line # and line
|
| while ((line = bufRead.readLine()) != null) {
|
| result.add(line);
|
| }
|
|
|
| bufRead.close();
|
| }
|
| catch (IOException e) { |
| LOGGER.error("IO exception reading command line file", e);
|
| }
|
|
|
| return result;
|
|
|
| }
|
| |
| /** |
| * Returns the Class object corresponding to the given name. The name may be |
| * of the following form: |
| * <ul> |
| * <li>A class name: "org.testng.TestNG"</li> |
| * <li>A class file name: "/testng/src/org/testng/TestNG.class"</li> |
| * <li>A class source name: "d:\testng\src\org\testng\TestNG.java"</li> |
| * </ul> |
| * |
| * @param file |
| * the class name. |
| * @return the class corresponding to the name specified. |
| */ |
| private static Class fileToClass(String file) { |
| Class result = null; |
| |
| if(!file.endsWith(".class") && !file.endsWith(".java")) { |
| // Doesn't end in .java or .class, assume it's a class name |
| result = ClassHelper.forName(file); |
| |
| if (null == result) { |
| throw new TestNGException("Cannot load class from file: " + file); |
| } |
| |
| return result; |
| } |
| |
| int classIndex = file.lastIndexOf(".class"); |
| if (-1 == classIndex) { |
| classIndex = file.lastIndexOf(".java"); |
| // |
| // if(-1 == classIndex) { |
| // result = ClassHelper.forName(file); |
| // |
| // if (null == result) { |
| // throw new TestNGException("Cannot load class from file: " + file); |
| // } |
| // |
| // return result; |
| // } |
| // |
| } |
| |
| // Transforms the file name into a class name. |
| |
| // Remove the ".class" or ".java" extension. |
| String shortFileName = file.substring(0, classIndex); |
| |
| // Split file name into segments. For example "c:/java/classes/com/foo/A" |
| // becomes {"c:", "java", "classes", "com", "foo", "A"} |
| String[] segments = shortFileName.split("[/\\\\]", -1); |
| |
| // |
| // Check if the last good root index works for this one. For example, if the previous |
| // name was "c:/java/classes/com/foo/A.class" then m_lastGoodRootIndex is 3 and we |
| // try to make a class name ignoring the first m_lastGoodRootIndex segments (3). This |
| // will succeed rapidly if the path is the same as the one from the previous name. |
| // |
| if (-1 != m_lastGoodRootIndex) { |
| |
| // TODO use a SringBuffer here |
| String className = segments[m_lastGoodRootIndex]; |
| for (int i = m_lastGoodRootIndex + 1; i < segments.length; i++) { |
| className += "." + segments[i]; |
| } |
| |
| result = ClassHelper.forName(className); |
| |
| if (null != result) { |
| return result; |
| } |
| } |
| |
| // |
| // We haven't found a good root yet, start by resolving the class from the end segment |
| // and work our way up. For example, if we start with "c:/java/classes/com/foo/A" |
| // we'll start by resolving "A", then "foo.A", then "com.foo.A" until something |
| // resolves. When it does, we remember the path we are at as "lastGoodRoodIndex". |
| // |
| |
| // TODO CQ use a StringBuffer here |
| String className = null; |
| for (int i = segments.length - 1; i >= 0; i--) { |
| if (null == className) { |
| className = segments[i]; |
| } |
| else { |
| className = segments[i] + "." + className; |
| } |
| |
| result = ClassHelper.forName(className); |
| |
| if (null != result) { |
| m_lastGoodRootIndex = i; |
| break; |
| } |
| } |
| |
| if (null == result) { |
| throw new TestNGException("Cannot load class from file: " + file); |
| } |
| |
| return result; |
| } |
| |
| // private static void ppp(Object msg) { |
| // System.out.println("[CMD]: " + msg); |
| // } |
| |
| /** |
| * Prints the usage message to System.out. This message describes all the command line |
| * options. |
| */ |
| public static void usage() { |
| System.out.println("Usage:"); |
| System.out.println("[" + OUTDIR_COMMAND_OPT + " output-directory]"); |
| System.out.println("\t\tdefault output directory to : " + TestNG.DEFAULT_OUTPUTDIR); |
| System.out.println("[" + TESTCLASS_COMMAND_OPT |
| + " list of .class files or list of class names]"); |
| System.out.println("[" + SRC_COMMAND_OPT + " a source directory]"); |
| |
| if (VersionInfo.IS_JDK14) { |
| System.out.println("[" + ANNOTATIONS_COMMAND_OPT + " " + AnnotationTypeEnum.JAVADOC.getName() + "]"); |
| System.out.println("\t\tSpecifies the default annotation type to be used in suites when none is explicitly specified."); |
| System.out.println("\t\tThis version of TestNG (14) only supports " + AnnotationTypeEnum.JAVADOC.getName() + " annotation type."); |
| System.out.println("\t\tFor interface compatibility reasons, we allow this value to be explicitly set to " + |
| AnnotationTypeEnum.JAVADOC.getName() + "\" "); |
| } |
| else { |
| System.out.println("[" + ANNOTATIONS_COMMAND_OPT + " " + AnnotationTypeEnum.JAVADOC.getName() + " or " |
| + AnnotationTypeEnum.JDK.getName() + "]"); |
| System.out.println("\t\tSpecifies the default annotation type to be used in suites when none is explicitly"); |
| System.out.println("\t\tspecified. This version of TestNG (15) supports both \"" |
| + AnnotationTypeEnum.JAVADOC.getName() + "\" and \"" + AnnotationTypeEnum.JDK.getName() + "\" annotation types."); |
| } |
| |
| System.out.println("[" + GROUPS_COMMAND_OPT + " comma-separated list of group names to be run]"); |
| System.out.println("\t\tworks only with " + TESTCLASS_COMMAND_OPT); |
| System.out.println("[" + EXCLUDED_GROUPS_COMMAND_OPT |
| + " comma-separated list of group names to be excluded]"); |
| System.out.println("\t\tworks only with " + TESTCLASS_COMMAND_OPT); |
| System.out.println("[" + TESTRUNNER_FACTORY_COMMAND_OPT |
| + " list of .class files or list of class names implementing " |
| + ITestRunnerFactory.class.getName() |
| + "]"); |
| System.out.println("[" + LISTENER_COMMAND_OPT |
| + " list of .class files or list of class names implementing " |
| + ITestListener.class.getName() |
| + " and/or " |
| + ISuiteListener.class.getName() |
| + "]"); |
| System.out.println("[" + PARALLEL_MODE |
| + " methods|tests]"); |
| System.out.println("\t\trun tests in parallel using the specified mode"); |
| System.out.println("[" + THREAD_COUNT |
| + " number of threads to use when running tests in parallel]"); |
| System.out.println("[" + SUITE_NAME_OPT + " name]"); |
| System.out.println("\t\tDefault name of test suite, if not specified in suite definition file or source code"); |
| System.out.println("[" + TEST_NAME_OPT + " Name]"); |
| System.out.println("\t\tDefault name of test, if not specified in suite definition file or source code"); |
| System.out.println("[suite definition files*]"); |
| System.out.println(""); |
| System.out.println("For details please consult documentation."); |
| } |
| } |