2121import org .testng .ITestListener ;
2222import org .testng .ITestNGMethod ;
2323import org .testng .ITestResult ;
24+ import org .testng .xml .XmlSuite ;
25+ import org .testng .xml .XmlTest ;
2426
2527import java .lang .management .ManagementFactory ;
2628import java .math .BigInteger ;
3335import java .util .List ;
3436import java .util .Map ;
3537import java .util .Objects ;
38+ import java .util .Optional ;
3639import java .util .UUID ;
3740import java .util .function .Consumer ;
3841import java .util .stream .Collectors ;
@@ -130,6 +133,9 @@ public void onFinish(ITestContext context) {
130133 public void onTestStart (ITestResult testResult ) {
131134 LOGGER .info ("onTestStart of " + testResult .getName ());
132135 Current current = currentTestResult .get ();
136+ if (current .isStarted ()) {
137+ current = refreshContext ();
138+ }
133139 current .test ();
134140 String parentUuid = getUniqueUuid (testResult .getTestContext ());
135141 ITestNGMethod method = testResult .getMethod ();
@@ -138,8 +144,8 @@ public void onTestStart(ITestResult testResult) {
138144 label ("package" , testClass .getName ()),
139145 label ("testClass" , testClass .getName ()),
140146 label ("testMethod" , method .getMethodName ()),
141- label ("parentSuite" , testClass . getXmlTest (). getSuite (). getName ( )),
142- label ("suite" , testClass . getXmlTest (). getName ( )),
147+ label ("parentSuite" , safeExtractSuiteName ( testClass )),
148+ label ("suite" , safeExtractTestTag ( testClass )),
143149 label ("host" , HOST ),
144150 label ("thread" , getThreadName ())
145151 );
@@ -171,15 +177,14 @@ public void onTestFailure(ITestResult result) {
171177 Current current = currentTestResult .get ();
172178
173179 if (current .isAfter ()) {
174- currentTestResult .remove ();
175- current = currentTestResult .get ();
180+ current = refreshContext ();
176181 }
177182
178183 //if test has failed without any setup
179184 if (!current .isStarted ()) {
180- onTestStart (result );
181- currentTestResult .remove ();
185+ createTestResutForUnexecutedTest (result );
182186 }
187+
183188 current .after ();
184189 Throwable throwable = result .getThrowable ();
185190 Status status = getStatus (throwable ).orElse (Status .BROKEN );
@@ -196,14 +201,12 @@ public void onTestSkipped(ITestResult result) {
196201
197202 //test is being skipped as dependent on failed test, closing context for previous test here
198203 if (current .isAfter ()) {
199- currentTestResult .remove ();
200- current = currentTestResult .get ();
204+ current = refreshContext ();
201205 }
202206
203207 //if test was skipped without any setup
204208 if (!current .isStarted ()) {
205- onTestStart (result );
206- currentTestResult .remove ();
209+ createTestResutForUnexecutedTest (result );
207210 }
208211 current .after ();
209212 StatusDetails details = getStatusDetails (result .getThrowable ()).orElse (null );
@@ -212,6 +215,11 @@ public void onTestSkipped(ITestResult result) {
212215 getLifecycle ().writeTestCase (current .getUuid ());
213216 }
214217
218+ private void createTestResutForUnexecutedTest (ITestResult result ) {
219+ onTestStart (result );
220+ currentTestResult .remove ();
221+ }
222+
215223 @ Override
216224 public void onTestFailedButWithinSuccessPercentage (ITestResult result ) {
217225 //do nothing
@@ -368,6 +376,16 @@ private MessageDigest getMessageDigest() {
368376 }
369377 }
370378
379+ private static String safeExtractSuiteName (ITestClass testClass ) {
380+ Optional <XmlTest > xmlTest = Optional .ofNullable (testClass .getXmlTest ());
381+ return xmlTest .map (XmlTest ::getSuite ).map (XmlSuite ::getName ).orElse ("Undefined suite" );
382+ }
383+
384+ private static String safeExtractTestTag (ITestClass testClass ) {
385+ Optional <XmlTest > xmlTest = Optional .ofNullable (testClass .getXmlTest ());
386+ return xmlTest .map (XmlTest ::getName ).orElse ("Undefined test tag" );
387+ }
388+
371389 private Label label (String name , String value ) {
372390 return new Label ().withName (name ).withValue (value );
373391 }
@@ -411,6 +429,11 @@ private Consumer<TestResult> setStatus(Status status, StatusDetails details) {
411429 .withStatusDetails (details );
412430 }
413431
432+ private Current refreshContext () {
433+ currentTestResult .remove ();
434+ return currentTestResult .get ();
435+ }
436+
414437 private static class Current {
415438 private final String uuid ;
416439 private CurrentStage currentStage ;
0 commit comments