Skip to content

Commit 317a92d

Browse files
authored
Merge pull request #1579 from krmahadevan/krmahadevan-fix-217
Exception in DataProvider doesn't fail test run
2 parents f4a6eb4 + d74e0f9 commit 317a92d

14 files changed

+297
-72
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
Current
2+
Fixed: GITHUB-217: exception in DataProvider doesn't fail test run (Krishnan Mahadevan)
23
Fixed: GITHUB-987: Parameters threadCount and parallel doesn't work with maven (Krishnan Mahadevan)
34
Fixed: GITHUB-1472: Optimize DynamicGraph.getUnfinishedNodes (Krishnan Mahadevan & Nathan Reynolds)
45
Fixed: GITHUB-1566: Invalid XML characters in Params in testng-results.xml (Krishnan Mahadevan)

src/main/java/org/testng/TestNG.java

Lines changed: 16 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.testng.internal.ClassHelper;
3030
import org.testng.internal.Configuration;
3131
import org.testng.internal.DynamicGraph;
32+
import org.testng.internal.ExitCode;
3233
import org.testng.internal.IConfiguration;
3334
import org.testng.internal.IResultListener2;
3435
import org.testng.internal.OverrideProcessor;
@@ -142,16 +143,9 @@ public class TestNG {
142143
private final Map<Class<? extends IReporter>, IReporter> m_reporters = Maps.newHashMap();
143144
private final Map<Class<? extends IDataProviderListener>, IDataProviderListener> m_dataProviderListeners = Maps.newHashMap();
144145

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;
149146

150147
public static final Integer DEFAULT_VERBOSE = 1;
151148

152-
private int m_status;
153-
private boolean m_hasTests= false;
154-
155149
// Command line suite parameters
156150
private int m_threadCount = -1;
157151
private XmlSuite.ParallelMode m_parallelMode = null;
@@ -185,6 +179,8 @@ public class TestNG {
185179
private final Map<Class<? extends IAlterSuiteListener>, IAlterSuiteListener> m_alterSuiteListeners= Maps.newHashMap();
186180

187181
private boolean m_isInitialized = false;
182+
private org.testng.internal.ExitCodeListener exitCodeListener;
183+
private ExitCode exitCode;
188184

189185
/**
190186
* Default constructor. Setting also usage of default listeners/reporters.
@@ -211,11 +207,10 @@ private void init(boolean useDefaultListeners) {
211207
}
212208

213209
public int getStatus() {
214-
return m_status;
215-
}
216-
217-
private void setStatus(int status) {
218-
m_status |= status;
210+
if (!exitCodeListener.hasTests()) {
211+
return ExitCode.HAS_NO_TEST;
212+
}
213+
return exitCode.getExitCode();
219214
}
220215

221216
/**
@@ -963,7 +958,8 @@ private void addReporter(Class<? extends IReporter> r) {
963958
}
964959

965960
private void initializeDefaultListeners() {
966-
addListener((ITestNGListener) new ExitCodeListener(this));
961+
this.exitCodeListener = new org.testng.internal.ExitCodeListener();
962+
addListener((ITestNGListener) this.exitCodeListener);
967963
if (m_useDefaultListeners) {
968964
addReporter(SuiteHTMLReporter.class);
969965
addReporter(Main.class);
@@ -1155,9 +1151,9 @@ public void run() {
11551151
}
11561152

11571153
runExecutionListeners(false /* finish */);
1154+
exitCode = this.exitCodeListener.getStatus();
11581155

1159-
if(!m_hasTests) {
1160-
setStatus(HAS_NO_TEST);
1156+
if(!exitCodeListener.hasTests()) {
11611157
if (TestRunner.getVerbose() > 1) {
11621158
System.err.println("[TestNG] No tests found. Nothing was run");
11631159
usage();
@@ -1243,7 +1239,6 @@ private void generateReports(List<ISuite> suiteRunners) {
12431239
*/
12441240
public List<ISuite> runSuitesLocally() {
12451241
if (m_suites.isEmpty()) {
1246-
setStatus(HAS_NO_TEST);
12471242
error("No test suite found. Nothing to run");
12481243
usage();
12491244
return Collections.emptyList();
@@ -1490,7 +1485,7 @@ public static TestNG privateMain(String[] argv, ITestListener listener) {
14901485
else {
14911486
error(ex.getMessage());
14921487
}
1493-
result.setStatus(HAS_FAILURE);
1488+
result.exitCode = ExitCode.newExitCodeRepresentingFailure();
14941489
}
14951490

14961491
return result;
@@ -1844,21 +1839,21 @@ protected static void validateCommandLineParameters(CommandLineArgs args) {
18441839
* @return true if at least one test failed.
18451840
*/
18461841
public boolean hasFailure() {
1847-
return (getStatus() & HAS_FAILURE) == HAS_FAILURE;
1842+
return this.exitCode.hasFailure();
18481843
}
18491844

18501845
/**
18511846
* @return true if at least one test failed within success percentage.
18521847
*/
18531848
public boolean hasFailureWithinSuccessPercentage() {
1854-
return (getStatus() & HAS_FSP) == HAS_FSP;
1849+
return this.exitCode.hasFailureWithinSuccessPercentage();
18551850
}
18561851

18571852
/**
18581853
* @return true if at least one test was skipped.
18591854
*/
18601855
public boolean hasSkip() {
1861-
return (getStatus() & HAS_SKIPPED) == HAS_SKIPPED;
1856+
return this.exitCode.hasSkip();
18621857
}
18631858

18641859
static void exitWithError(String msg) {
@@ -1951,30 +1946,10 @@ public static TestNG getDefault() {
19511946
return m_instance;
19521947
}
19531948

1954-
/**
1955-
* @deprecated since 5.1
1956-
*/
1957-
@Deprecated
1958-
public void setHasFailure(boolean hasFailure) {
1959-
m_status |= HAS_FAILURE;
1960-
}
1961-
1962-
/**
1963-
* @deprecated since 5.1
1964-
*/
19651949
@Deprecated
1966-
public void setHasFailureWithinSuccessPercentage(boolean hasFailureWithinSuccessPercentage) {
1967-
m_status |= HAS_FSP;
1968-
}
1969-
19701950
/**
1971-
* @deprecated since 5.1
1951+
* @deprecated - This class stands deprecated as of TestNG v6.13
19721952
*/
1973-
@Deprecated
1974-
public void setHasSkip(boolean hasSkip) {
1975-
m_status |= HAS_SKIPPED;
1976-
}
1977-
19781953
public static class ExitCodeListener implements IResultListener2 {
19791954
private TestNG m_mainRunner;
19801955

@@ -1993,21 +1968,16 @@ public void beforeConfiguration(ITestResult tr) {
19931968
@Override
19941969
public void onTestFailure(ITestResult result) {
19951970
setHasRunTests();
1996-
m_mainRunner.setStatus(HAS_FAILURE);
19971971
}
19981972

19991973
@Override
20001974
public void onTestSkipped(ITestResult result) {
20011975
setHasRunTests();
2002-
if ((m_mainRunner.getStatus() & HAS_FAILURE) != 0) {
2003-
m_mainRunner.setStatus(HAS_SKIPPED);
2004-
}
20051976
}
20061977

20071978
@Override
20081979
public void onTestFailedButWithinSuccessPercentage(ITestResult result) {
20091980
setHasRunTests();
2010-
m_mainRunner.setStatus(HAS_FSP);
20111981
}
20121982

20131983
@Override
@@ -2030,23 +2000,20 @@ public void onTestStart(ITestResult result) {
20302000
}
20312001

20322002
private void setHasRunTests() {
2033-
m_mainRunner.m_hasTests= true;
20342003
}
20352004

20362005
/**
20372006
* @see org.testng.IConfigurationListener#onConfigurationFailure(org.testng.ITestResult)
20382007
*/
20392008
@Override
20402009
public void onConfigurationFailure(ITestResult itr) {
2041-
m_mainRunner.setStatus(HAS_FAILURE);
20422010
}
20432011

20442012
/**
20452013
* @see org.testng.IConfigurationListener#onConfigurationSkip(org.testng.ITestResult)
20462014
*/
20472015
@Override
20482016
public void onConfigurationSkip(ITestResult itr) {
2049-
m_mainRunner.setStatus(HAS_SKIPPED);
20502017
}
20512018

20522019
/**

src/main/java/org/testng/TestNGAntTask.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.apache.tools.ant.types.resources.FileResource;
3737
import org.apache.tools.ant.types.selectors.FilenameSelector;
3838
import org.testng.collections.Lists;
39+
import org.testng.internal.ExitCode;
3940
import org.testng.internal.Utils;
4041
import org.testng.reporters.VerboseReporter;
4142

@@ -721,10 +722,10 @@ private void ppp(String string) {
721722
protected void actOnResult(int exitValue, boolean wasKilled) {
722723
if(exitValue == -1) {
723724
executeHaltTarget(exitValue);
724-
throw new BuildException("an error occured when running TestNG tests");
725+
throw new BuildException("an error occurred when running TestNG tests");
725726
}
726727

727-
if((exitValue & TestNG.HAS_NO_TEST) == TestNG.HAS_NO_TEST) {
728+
if((exitValue & ExitCode.HAS_NO_TEST) == ExitCode.HAS_NO_TEST) {
728729
if(m_haltOnFailure) {
729730
executeHaltTarget(exitValue);
730731
throw new BuildException("No tests were run");
@@ -738,7 +739,7 @@ protected void actOnResult(int exitValue, boolean wasKilled) {
738739
}
739740
}
740741

741-
boolean failed= ((exitValue & TestNG.HAS_FAILURE) == TestNG.HAS_FAILURE) || wasKilled;
742+
boolean failed= (ExitCode.hasFailure(exitValue)) || wasKilled;
742743
if(failed) {
743744
final String msg= wasKilled ? "The tests timed out and were killed." : "The tests failed.";
744745
if(m_haltOnFailure) {
@@ -754,7 +755,7 @@ protected void actOnResult(int exitValue, boolean wasKilled) {
754755
}
755756
}
756757

757-
if((exitValue & TestNG.HAS_SKIPPED) == TestNG.HAS_SKIPPED) {
758+
if(ExitCode.hasSkipped(exitValue)) {
758759
if(m_haltOnSkipped) {
759760
executeHaltTarget(exitValue);
760761
throw new BuildException("There are TestNG SKIPPED tests");
@@ -768,7 +769,7 @@ protected void actOnResult(int exitValue, boolean wasKilled) {
768769
}
769770
}
770771

771-
if((exitValue & TestNG.HAS_FSP) == TestNG.HAS_FSP) {
772+
if(ExitCode.hasFailureWithinSuccessPercentage(exitValue)) {
772773
if(m_haltOnFSP) {
773774
executeHaltTarget(exitValue);
774775
throw new BuildException("There are TestNG FAILED WITHIN SUCCESS PERCENTAGE tests");
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package org.testng.internal;
2+
3+
import org.testng.IResultMap;
4+
import org.testng.ITestContext;
5+
6+
import java.util.BitSet;
7+
8+
/**
9+
* |---------------------|---------|--------|-------------|------------------------------------------|
10+
* | FailedWithinSuccess | Skipped | Failed | Status Code | Remarks |
11+
* |---------------------|---------|--------|-------------|------------------------------------------|
12+
* | 0 | 0 | 0 | 0 | Passed tests |
13+
* | 0 | 0 | 1 | 1 | Failed tests |
14+
* | 0 | 1 | 0 | 2 | Skipped tests |
15+
* | 0 | 1 | 1 | 3 | Skipped/Failed tests |
16+
* | 1 | 0 | 0 | 4 | FailedWithinSuccess tests |
17+
* | 1 | 0 | 1 | 5 | FailedWithinSuccess/Failed tests |
18+
* | 1 | 1 | 0 | 6 | FailedWithinSuccess/Skipped tests |
19+
* | 1 | 1 | 1 | 7 | FailedWithinSuccess/Skipped/Failed tests |
20+
* |---------------------|---------|--------|-------------|------------------------------------------|
21+
*/
22+
public class ExitCode {
23+
24+
public static final int HAS_NO_TEST = 8;
25+
private static final int FAILED_WITHIN_SUCCESS = 4;
26+
private static final int SKIPPED = 2;
27+
private static final int FAILED = 1;
28+
private static final int SIZE = 3;
29+
30+
private final BitSet exitCodeBits;
31+
32+
ExitCode() {
33+
this(new BitSet(SIZE));
34+
}
35+
36+
public static boolean hasFailureWithinSuccessPercentage(int returnCode) {
37+
return (returnCode & FAILED_WITHIN_SUCCESS) == FAILED_WITHIN_SUCCESS;
38+
}
39+
40+
public static boolean hasSkipped(int returnCode) {
41+
return (returnCode & SKIPPED) == SKIPPED;
42+
}
43+
44+
public static boolean hasFailure(int returnCode) {
45+
return (returnCode & FAILED) == FAILED;
46+
}
47+
48+
public static ExitCode newExitCodeRepresentingFailure() {
49+
BitSet bitSet = new BitSet(SIZE);
50+
bitSet.set(0, true);
51+
bitSet.set(1, false);
52+
bitSet.set(2, false);
53+
54+
return new ExitCode(bitSet);
55+
}
56+
57+
private ExitCode(BitSet exitCodeBits) {
58+
this.exitCodeBits = exitCodeBits;
59+
}
60+
61+
void computeAndUpdate(ITestContext context) {
62+
computeAndUpdate(0, context.getFailedTests(), context.getFailedConfigurations());
63+
computeAndUpdate(1, context.getSkippedTests(), context.getSkippedConfigurations());
64+
computeAndUpdate(2, context.getFailedButWithinSuccessPercentageTests(), null);
65+
}
66+
67+
private void computeAndUpdate(int index, IResultMap testResults, IResultMap configResults) {
68+
boolean containsResults = testResults.size() != 0;
69+
if (configResults != null) {
70+
containsResults = containsResults || configResults.size() != 0;
71+
}
72+
if (containsResults) {
73+
this.exitCodeBits.set(index);
74+
}
75+
}
76+
77+
public boolean hasFailure() {
78+
return exitCodeBits.get(0);
79+
}
80+
81+
public boolean hasSkip() {
82+
return exitCodeBits.get(1);
83+
}
84+
85+
public boolean hasFailureWithinSuccessPercentage() {
86+
return exitCodeBits.get(2);
87+
}
88+
89+
public int getExitCode() {
90+
int exitCode = 0;
91+
for (int i = 0; i < exitCodeBits.length(); i++) {
92+
if (exitCodeBits.get(i)) {
93+
exitCode = exitCode | (1 << i);
94+
}
95+
}
96+
97+
return exitCode;
98+
}
99+
}

0 commit comments

Comments
 (0)