Implemented -skipfailedinvocationcounts (also in ant and testng.xml).
diff --git a/src/main/org/testng/SuiteRunner.java b/src/main/org/testng/SuiteRunner.java
index db9d78d..d09fe8c 100644
--- a/src/main/org/testng/SuiteRunner.java
+++ b/src/main/org/testng/SuiteRunner.java
@@ -58,6 +58,7 @@
transient private IAnnotationFinder m_jdkAnnotationFinder;
transient private IObjectFactory m_objectFactory;
+ transient private Boolean m_skipFailedInvocationCounts = Boolean.FALSE;
// transient private IAnnotationTransformer m_annotationTransformer = null;
@@ -167,7 +168,7 @@
if (null == m_tmpRunnerFactory) {
factory = new DefaultTestRunnerFactory(
m_testlisteners.toArray(new ITestListener[m_testlisteners.size()]),
- m_useDefaultListeners);
+ m_useDefaultListeners, m_skipFailedInvocationCounts);
}
else {
factory = new ProxyTestRunnerFactory(
@@ -431,21 +432,31 @@
public static class DefaultTestRunnerFactory implements ITestRunnerFactory {
private ITestListener[] m_failureGenerators;
private boolean m_useDefaultListeners;
+ private boolean m_skipFailedInvocationCounts;
- public DefaultTestRunnerFactory(ITestListener[] failureListeners, boolean useDefaultListeners) {
+ public DefaultTestRunnerFactory(ITestListener[] failureListeners,
+ boolean useDefaultListeners,
+ boolean skipFailedInvocationCounts)
+ {
m_failureGenerators = failureListeners;
m_useDefaultListeners = useDefaultListeners;
+ m_skipFailedInvocationCounts = skipFailedInvocationCounts;
}
/**
* @see ITestRunnerFactory#newTestRunner(org.testng.ISuite, org.testng.xml.XmlTest)
*/
public TestRunner newTestRunner(ISuite suite, XmlTest test) {
+ boolean skip = m_skipFailedInvocationCounts;
+ if (! skip) {
+ skip = test.skipFailedInvocationCounts();
+ }
TestRunner testRunner =
new TestRunner(suite,
test,
suite.getOutputDirectory(),
- suite.getAnnotationFinder(test.getAnnotations()));
+ suite.getAnnotationFinder(test.getAnnotations()),
+ skip);
if (m_useDefaultListeners) {
testRunner.addListener(new TestHTMLReporter());
@@ -462,7 +473,7 @@
for (ITestListener itl : m_failureGenerators) {
testRunner.addListener(itl);
}
-
+
return testRunner;
}
}
@@ -501,11 +512,17 @@
}
private SuiteRunState m_suiteState= new SuiteRunState();
-
+
/**
* @see org.testng.ISuite#getSuiteState()
*/
public SuiteRunState getSuiteState() {
return m_suiteState;
}
+
+ public void setSkipFailedInvocationCounts(Boolean skipFailedInvocationCounts) {
+ if (skipFailedInvocationCounts != null) {
+ m_skipFailedInvocationCounts = skipFailedInvocationCounts;
+ }
+ }
}
diff --git a/src/main/org/testng/TestNG.java b/src/main/org/testng/TestNG.java
index 2361ca7..127f32a 100644
--- a/src/main/org/testng/TestNG.java
+++ b/src/main/org/testng/TestNG.java
@@ -602,6 +602,8 @@
private IAnnotationTransformer m_annotationTransformer = new DefaultAnnotationTransformer();
+ private Boolean m_skipFailedInvocationCounts = false;
+
/**
* Sets the level of verbosity. This value will override the value specified
* in the test suites.
@@ -756,6 +758,15 @@
xmlSuite.setJUnit(m_isJUnit);
}
+ // If the skip flag was invoked on the command line, it
+ // takes precedence
+ if (null != m_skipFailedInvocationCounts) {
+ xmlSuite.setSkipFailedInvocationCounts(m_skipFailedInvocationCounts);
+ }
+ else {
+ m_skipFailedInvocationCounts = xmlSuite.skipFailedInvocationCounts();
+ }
+
// TODO CQ is this OK? Should the command line verbose flag override
// what is explicitly specified in the suite?
if (null != m_verbose) {
@@ -781,7 +792,12 @@
m_outputDir,
m_testRunnerFactory,
m_useDefaultListeners,
- new IAnnotationFinder[] {m_javadocAnnotationFinder, m_jdkAnnotationFinder}, m_objectFactory);
+ new IAnnotationFinder[] {
+ m_javadocAnnotationFinder,
+ m_jdkAnnotationFinder
+ },
+ m_objectFactory);
+ result.setSkipFailedInvocationCounts(m_skipFailedInvocationCounts);
for (ISuiteListener isl : m_suiteListeners) {
result.addListener(isl);
@@ -877,6 +893,9 @@
setJUnit((Boolean) cmdLineArgs.get(TestNGCommandLineArgs.JUNIT_DEF_OPT));
setMaster( (String)cmdLineArgs.get(TestNGCommandLineArgs.MASTER_OPT));
setSlave( (String)cmdLineArgs.get(TestNGCommandLineArgs.SLAVE_OPT));
+ setSkipFailedInvocationCounts(
+ (Boolean) cmdLineArgs.get(
+ TestNGCommandLineArgs.SKIP_FAILED_INVOCATION_COUNT_OPT));
String parallelMode = (String) cmdLineArgs.get(TestNGCommandLineArgs.PARALLEL_MODE);
if (parallelMode != null) {
@@ -917,6 +936,10 @@
}
}
+ private void setSkipFailedInvocationCounts(Boolean skip) {
+ m_skipFailedInvocationCounts = skip;
+ }
+
private void addReporter(ReporterConfig reporterConfig) {
Object instance = reporterConfig.newReporterInstance();
if (instance != null) {
@@ -1060,6 +1083,14 @@
return m_annotationTransformer;
}
+ public boolean getSkipFailedInvocationCounts() {
+ return m_skipFailedInvocationCounts;
+ }
+
+ public void setSkipFailedInvocationCounts(boolean skip) {
+ m_skipFailedInvocationCounts = skip;
+ }
+
public void setAnnotationTransformer(IAnnotationTransformer t) {
m_annotationTransformer = t;
}
diff --git a/src/main/org/testng/TestNGAntTask.java b/src/main/org/testng/TestNGAntTask.java
index fa8a755..06a48ee 100644
--- a/src/main/org/testng/TestNGAntTask.java
+++ b/src/main/org/testng/TestNGAntTask.java
@@ -134,6 +134,7 @@
public String m_useDefaultListeners;
private String m_suiteName="Ant suite";
private String m_testName="Ant test";
+ private Boolean m_skipFailedInvocationCounts;
/**
* The list of report listeners added via <reporter> sub-element of the Ant task
@@ -464,11 +465,18 @@
List<String> argv= new ArrayList<String>();
- if(null != m_isJUnit) {
+ if (null != m_isJUnit) {
if(m_isJUnit.booleanValue()) {
argv.add(TestNGCommandLineArgs.JUNIT_DEF_OPT);
}
}
+
+ if (null != m_skipFailedInvocationCounts) {
+ if(m_skipFailedInvocationCounts.booleanValue()) {
+ argv.add(TestNGCommandLineArgs.SKIP_FAILED_INVOCATION_COUNT_OPT);
+ }
+ }
+
if(null != m_verbose) {
argv.add(TestNGCommandLineArgs.LOG);
@@ -1011,4 +1019,8 @@
public void addConfiguredReporter(ReporterConfig reporterConfig) {
reporterConfigs.add(reporterConfig);
}
+
+ public void setSkipFailedInvocationCounts(boolean skip) {
+ m_skipFailedInvocationCounts = Boolean.valueOf(skip);
+ }
}
diff --git a/src/main/org/testng/TestNGCommandLineArgs.java b/src/main/org/testng/TestNGCommandLineArgs.java
index 2e28493..16c78f1 100644
--- a/src/main/org/testng/TestNGCommandLineArgs.java
+++ b/src/main/org/testng/TestNGCommandLineArgs.java
@@ -69,6 +69,8 @@
public static final String PARALLEL_MODE = "-parallel";
public static final String SUITE_NAME_OPT = "-suitename";
public static final String TEST_NAME_OPT = "-testname";
+ public static final String SKIP_FAILED_INVOCATION_COUNT_OPT = "-skipfailedinvocationcounts";
+
/**
* Used to pass a reporter configuration in the form <code>-reporter <reporter_name_or_class>:option=value[,option=value]</code>
*/
@@ -354,6 +356,9 @@
i++;
}
}
+ else if (SKIP_FAILED_INVOCATION_COUNT_OPT.equalsIgnoreCase(argv[i])) {
+ arguments.put(SKIP_FAILED_INVOCATION_COUNT_OPT, Boolean.TRUE);
+ }
//
// Unknown option
//
diff --git a/src/main/org/testng/TestRunner.java b/src/main/org/testng/TestRunner.java
index 2bb8627..0afe5c3 100644
--- a/src/main/org/testng/TestRunner.java
+++ b/src/main/org/testng/TestRunner.java
@@ -62,6 +62,7 @@
transient private List<IConfigurationListener> m_configurationListeners= new ArrayList<IConfigurationListener>();
transient private IConfigurationListener m_confListener= new ConfigurationListener();
+ transient private boolean m_skipFailedInvocationCounts;
/**
* All the test methods we found, associated with their respective classes.
@@ -120,31 +121,38 @@
public TestRunner(ISuite suite,
XmlTest test,
String outputDirectory,
- IAnnotationFinder finder)
+ IAnnotationFinder finder,
+ boolean skipFailedInvocationCounts)
{
- init(suite, test, outputDirectory, finder);
+ init(suite, test, outputDirectory, finder, skipFailedInvocationCounts);
}
- public TestRunner(ISuite suite, XmlTest test, IAnnotationFinder finder)
+ public TestRunner(ISuite suite, XmlTest test,
+ IAnnotationFinder finder, boolean skipFailedInvocationCounts)
{
- init(suite, test, suite.getOutputDirectory(), finder);
+ init(suite, test, suite.getOutputDirectory(), finder, skipFailedInvocationCounts);
}
- public TestRunner(ISuite suite, XmlTest test) {
+ public TestRunner(ISuite suite, XmlTest test,
+ boolean skipFailedInvocationCounts)
+ {
init(suite, test, suite.getOutputDirectory(),
- suite.getAnnotationFinder(test.getAnnotations()));
+ suite.getAnnotationFinder(test.getAnnotations()),
+ skipFailedInvocationCounts);
}
private void init(ISuite suite,
XmlTest test,
String outputDirectory,
- IAnnotationFinder annotationFinder)
+ IAnnotationFinder annotationFinder,
+ boolean skipFailedInvocationCounts)
{
m_xmlTest= test;
m_suite = suite;
m_testName = test.getName();
m_host = suite.getHost();
m_testClassesFromXml= test.getXmlClasses();
+ m_skipFailedInvocationCounts = skipFailedInvocationCounts;
m_packageNamesFromXml= test.getXmlPackages();
if(null != m_packageNamesFromXml) {
@@ -154,7 +162,9 @@
}
m_annotationFinder= annotationFinder;
- m_invoker= new Invoker(this, this, m_suite.getSuiteState(), m_annotationFinder);
+ m_invoker =
+ new Invoker(this, this, m_suite.getSuiteState(),
+ m_annotationFinder, m_skipFailedInvocationCounts);
setVerbose(test.getVerbose());
diff --git a/src/main/org/testng/internal/IInvoker.java b/src/main/org/testng/internal/IInvoker.java
index cd5d344..e35fdaa 100644
--- a/src/main/org/testng/internal/IInvoker.java
+++ b/src/main/org/testng/internal/IInvoker.java
@@ -52,4 +52,5 @@
ConfigurationGroupMethods groupMethods,
Object[] instances,
ITestContext testContext);
+
}
diff --git a/src/main/org/testng/internal/Invoker.java b/src/main/org/testng/internal/Invoker.java
index d661cea..9ce8f36 100644
--- a/src/main/org/testng/internal/Invoker.java
+++ b/src/main/org/testng/internal/Invoker.java
@@ -49,15 +49,18 @@
private ITestResultNotifier m_notifier;
private IAnnotationFinder m_annotationFinder;
private SuiteRunState m_suiteState;
+ private boolean m_skipFailedInvocationCounts;
public Invoker(ITestContext testContext,
ITestResultNotifier notifier,
SuiteRunState state,
- IAnnotationFinder annotationFinder) {
+ IAnnotationFinder annotationFinder,
+ boolean skipFailedInvocationCounts) {
m_testContext= testContext;
m_suiteState= state;
m_notifier= notifier;
m_annotationFinder= annotationFinder;
+ m_skipFailedInvocationCounts = skipFailedInvocationCounts;
}
/**
@@ -764,7 +767,7 @@
// - try to remove the isWithinThreadedMethod: still needed to determine the @BeforeMethod + @AfterMethod
// - [DONE] solve the results different approaches: assignment and addAll
//
- // HINT: for invocationCount>1 and threadPoolSize>1 the method will be invoked on a thread pool
+ // For invocationCount>1 and threadPoolSize>1 the method will be invoked on a thread pool
int invocationCount = (testMethod.getThreadPoolSize() > 1 ? 1 : testMethod.getInvocationCount());
int failureCount = 0;
@@ -780,7 +783,7 @@
//
if (MethodHelper.isEnabled(testMethod.getMethod(), m_annotationFinder)) {
//
- // HINT: If threadPoolSize specified, run this method in its own pool thread.
+ // If threadPoolSize specified, run this method in its own pool thread.
//
if (testMethod.getThreadPoolSize() > 1 && testMethod.getInvocationCount() > 1) {
return invokePooledTestMethods(testMethod, allTestMethods, suite,
@@ -849,14 +852,36 @@
for (int i = 0; i < failedInstances.size(); i++) {
List<ITestResult> retryResults = new ArrayList<ITestResult>();
- failureCount = retryFailed(failedInstances.toArray(),
- i, testMethod, suite, testClass, beforeMethods,
- afterMethods, groupMethods, retryResults,
- failureCount, expectedExceptionClasses,
- testContext, parameters, parametersIndex);
- result.addAll(retryResults);
+ failureCount =
+ retryFailed(failedInstances.toArray(),
+ i, testMethod, suite, testClass, beforeMethods,
+ afterMethods, groupMethods, retryResults,
+ failureCount, expectedExceptionClasses,
+ testContext, parameters, parametersIndex);
+ result.addAll(retryResults);
}
}
+
+ //
+ // If we have a failure, skip all the
+ // other invocationCounts
+ //
+ if (failureCount > 0 && m_skipFailedInvocationCounts) {
+ while (invocationCount-- > 0) {
+ ITestResult r =
+ new TestResult(testMethod.getTestClass(),
+ instances[0],
+ testMethod,
+ null,
+ start,
+ System.currentTimeMillis());
+ r.setStatus(TestResult.SKIP);
+ result.add(r);
+ runTestListeners(r);
+ m_notifier.addSkippedTest(testMethod, r);
+ }
+ break;
+ }
}
parametersIndex++;
}
diff --git a/src/main/org/testng/remote/RemoteTestNG.java b/src/main/org/testng/remote/RemoteTestNG.java
index c147b80..d14cd11 100644
--- a/src/main/org/testng/remote/RemoteTestNG.java
+++ b/src/main/org/testng/remote/RemoteTestNG.java
@@ -99,8 +99,10 @@
if(null == m_customTestRunnerFactory) {
m_customTestRunnerFactory= new ITestRunnerFactory() {
public TestRunner newTestRunner(ISuite suite, XmlTest xmlTest) {
- TestRunner runner= new TestRunner(suite, xmlTest);
- if(m_useDefaultListeners) {
+ TestRunner runner =
+ new TestRunner(suite, xmlTest,
+ false /*skipFailedInvocationCounts */);
+ if (m_useDefaultListeners) {
runner.addListener(new TestHTMLReporter());
runner.addListener(new JUnitXMLReporter());
}
diff --git a/src/main/org/testng/remote/SuiteDispatcher.java b/src/main/org/testng/remote/SuiteDispatcher.java
index 76442d4..b875836 100644
--- a/src/main/org/testng/remote/SuiteDispatcher.java
+++ b/src/main/org/testng/remote/SuiteDispatcher.java
@@ -114,6 +114,7 @@
tmpSuite.setXmlPackages(suite.getXmlPackages());
tmpSuite.setAnnotations(suite.getAnnotations());
tmpSuite.setJUnit(suite.isJUnit());
+ tmpSuite.setSkipFailedInvocationCounts(suite.skipFailedInvocationCounts());
tmpSuite.setName("Temporary suite for " + test.getName());
tmpSuite.setParallel(suite.getParallel());
tmpSuite.setParameters(suite.getParameters());
diff --git a/src/main/org/testng/xml/TestNGContentHandler.java b/src/main/org/testng/xml/TestNGContentHandler.java
index 9349718..6746734 100644
--- a/src/main/org/testng/xml/TestNGContentHandler.java
+++ b/src/main/org/testng/xml/TestNGContentHandler.java
@@ -134,6 +134,10 @@
Utils.log("Parser", 1, "[WARN] Unknown value of attribute 'parallel' at suite level: '" + parallel + "'.");
}
}
+ String skip = attributes.getValue("skipfailedinvocationcounts");
+ if (skip != null) {
+ m_currentSuite.setSkipFailedInvocationCounts(Boolean.valueOf(skip));
+ }
String threadCount = attributes.getValue("thread-count");
if (null != threadCount) {
m_currentSuite.setThreadCount(Integer.parseInt(threadCount));
@@ -222,6 +226,10 @@
if (null != jUnit) {
m_currentTest.setJUnit( Boolean.valueOf(jUnit).booleanValue());
}
+ String skip = attributes.getValue("skipfailedinvocationcounts");
+ if (skip != null) {
+ m_currentTest.setSkipFailedInvocationCounts(Boolean.valueOf(skip).booleanValue());
+ }
String parallel = attributes.getValue("parallel");
if (null != parallel) {
if(XmlSuite.PARALLEL_METHODS.equals(parallel)
diff --git a/src/main/org/testng/xml/XmlSuite.java b/src/main/org/testng/xml/XmlSuite.java
index 88ed23e..cd3959a 100644
--- a/src/main/org/testng/xml/XmlSuite.java
+++ b/src/main/org/testng/xml/XmlSuite.java
@@ -54,6 +54,8 @@
/** JUnit compatibility flag. */
private Boolean m_isJUnit = Boolean.FALSE;
+ private Boolean m_skipFailedInvocationCounts = Boolean.FALSE;
+
/** The thread count. */
private int m_threadCount = 5;
@@ -326,7 +328,7 @@
public Boolean isJUnit() {
return m_isJUnit;
}
-
+
/**
* Sets the JUnit compatibility flag.
*
@@ -336,6 +338,14 @@
m_isJUnit = isJUnit;
}
+ public Boolean skipFailedInvocationCounts() {
+ return m_skipFailedInvocationCounts;
+ }
+
+ public void setSkipFailedInvocationCounts(boolean skip) {
+ m_skipFailedInvocationCounts = skip;
+ }
+
/**
* Sets the XML packages.
*
@@ -372,6 +382,9 @@
p.setProperty("thread-count", String.valueOf(getThreadCount()));
p.setProperty("annotations", getAnnotations());
p.setProperty("junit", m_isJUnit != null ? m_isJUnit.toString() : "false"); // TESTNG-141
+ p.setProperty("skipfailedinvocationCounts",
+ m_skipFailedInvocationCounts != null
+ ? m_skipFailedInvocationCounts.toString() : "false");
if(null != m_objectFactory)
p.setProperty("object-factory", m_objectFactory.getClass().getName());
xsb.push("suite", p);
@@ -455,6 +468,7 @@
result.setBeanShellExpression(getExpression());
result.setMethodSelectors(getMethodSelectors());
result.setJUnit(isJUnit()); // TESTNG-141
+ result.setSkipFailedInvocationCounts(skipFailedInvocationCounts());
result.setObjectFactory(getObjectFactory());
return result;
}
diff --git a/src/main/org/testng/xml/XmlTest.java b/src/main/org/testng/xml/XmlTest.java
index 3a74ccf..bcd9ad9 100644
--- a/src/main/org/testng/xml/XmlTest.java
+++ b/src/main/org/testng/xml/XmlTest.java
@@ -43,6 +43,7 @@
private List<XmlPackage> m_xmlPackages = new ArrayList<XmlPackage>();
private String m_timeOut;
+ private Boolean m_skipFailedInvocationCounts;
/**
* Constructs a <code>XmlTest</code> and adds it to suite's list of tests.
@@ -189,6 +190,22 @@
m_isJUnit = isJUnit;
}
+ public void setSkipFailedInvocationCounts(boolean skip) {
+ m_skipFailedInvocationCounts = skip;
+ }
+
+ /**
+ * @return Returns the isJUnit.
+ */
+ public boolean skipFailedInvocationCounts() {
+ Boolean result = m_skipFailedInvocationCounts;
+ if (null == result) {
+ result = m_suite.skipFailedInvocationCounts();
+ }
+
+ return result;
+ }
+
public void addMetaGroup(String name, List<String> metaGroup) {
m_metaGroups.put(name, metaGroup);
}