@@ -508,52 +508,49 @@ private static void setTestStatus(ITestResult result, int status) {
508508 private static class StatusHolder {
509509
510510 boolean handled = false ;
511+ int originalStatus ;
511512 int status ;
512513 }
513514
514- private void handleInvocationResults (
515+ private void handleInvocationResult (
515516 ITestNGMethod testMethod ,
516517 ITestResult testResult ,
517518 FailureContext failure ,
518519 StatusHolder holder ,
519- boolean wasResultUnaltered ) {
520- //
521- // Go through all the results and create a TestResult for each of them
522- //
523- List <ITestResult > resultsToRetry = Lists .newArrayList ();
524-
525- Throwable ite = testResult .getThrowable ();
526- int status =
527- computeTestStatusComparingTestResultAndStatusHolder (testResult , holder , wasResultUnaltered );
528- boolean handled = holder .handled ;
529- IRetryAnalyzer retryAnalyzer = testMethod .getRetryAnalyzer (testResult );
530-
531- boolean willRetry =
532- retryAnalyzer != null
533- && status == ITestResult .FAILURE
534- && failure .instances != null
535- && retryAnalyzer .retry (testResult );
520+ boolean willRetry ) {
536521
537522 if (willRetry ) {
538- resultsToRetry .add (testResult );
539523 Object instance = testResult .getInstance ();
540524 if (!failure .instances .contains (instance )) {
541525 failure .instances .add (instance );
542526 }
543527 testResult .setStatus (ITestResult .SKIP );
544528 testResult .setWasRetried (true );
545529 } else {
546- testResult .setStatus (status );
547- if (status == ITestResult .FAILURE && !handled ) {
530+ testResult .setStatus (holder . status );
531+ if (holder . status == ITestResult .FAILURE && !holder . handled ) {
548532 int count = failure .count ++;
549533 if (testMethod .isDataDriven ()) {
550534 count = 0 ;
551535 }
552- handleException (ite , testMethod , testResult , count );
536+ handleException (testResult . getThrowable () , testMethod , testResult , count );
553537 }
554538 }
555539 }
556540
541+ private boolean shouldRetryTestMethod (
542+ ITestNGMethod testMethod ,
543+ ITestResult testResult ,
544+ FailureContext failure ,
545+ StatusHolder holder ) {
546+ IRetryAnalyzer retryAnalyzer = testMethod .getRetryAnalyzer (testResult );
547+
548+ return retryAnalyzer != null
549+ && holder .status == ITestResult .FAILURE
550+ && failure .instances != null
551+ && retryAnalyzer .retry (testResult );
552+ }
553+
557554 // pass both paramValues and paramIndex to be thread safe in case parallel=true + dataprovider.
558555 private ITestResult invokeMethod (
559556 TestMethodArguments arguments , XmlSuite suite , FailureContext failureContext ) {
@@ -597,7 +594,8 @@ private ITestResult invokeMethod(
597594 testResult .setMethod (arguments .getTestMethod ());
598595 invokedMethod = new InvokedMethod (startTime , result );
599596 invokeListenersForSkippedTestResult (result , invokedMethod );
600- runAfterGroupsConfigurations (arguments , suite , testResult );
597+ runAfterConfigurations (arguments , suite , testResult );
598+ runAfterGroupsConfigurations (arguments );
601599
602600 return result ;
603601 }
@@ -699,11 +697,12 @@ private ITestResult invokeMethod(
699697 StatusHolder holder =
700698 considerExceptions (
701699 arguments .getTestMethod (), testResult , expectedExceptionClasses , failureContext );
702- int statusBeforeListenerInvocation = testResult .getStatus ();
703700 runInvokedMethodListeners (AFTER_INVOCATION , invokedMethod , testResult );
704- boolean wasResultUnaltered = statusBeforeListenerInvocation == testResult .getStatus ();
705- handleInvocationResults (
706- arguments .getTestMethod (), testResult , failureContext , holder , wasResultUnaltered );
701+ updateStatusHolderAccordingToTestResult (testResult , holder );
702+ boolean willRetryMethod =
703+ shouldRetryTestMethod (arguments .getTestMethod (), testResult , failureContext , holder );
704+ handleInvocationResult (
705+ arguments .getTestMethod (), testResult , failureContext , holder , willRetryMethod );
707706
708707 // If this method has a data provider and just failed, memorize the number
709708 // at which it failed.
@@ -730,7 +729,10 @@ private ITestResult invokeMethod(
730729
731730 collectResults (arguments .getTestMethod (), testResult );
732731
733- runAfterGroupsConfigurations (arguments , suite , testResult );
732+ runAfterConfigurations (arguments , suite , testResult );
733+ if (!willRetryMethod ) {
734+ runAfterGroupsConfigurations (arguments );
735+ }
734736
735737 // Reset the test result last. If we do this too early, Reporter.log()
736738 // invocations from listeners will be discarded
@@ -740,13 +742,15 @@ private ITestResult invokeMethod(
740742 return testResult ;
741743 }
742744
743- private void runAfterGroupsConfigurations (
745+ private void runAfterConfigurations (
744746 TestMethodArguments arguments , XmlSuite suite , TestResult testResult ) {
745747 ITestNGMethod [] teardownConfigMethods =
746748 TestNgMethodUtils .filterTeardownConfigurationMethods (
747749 arguments .getTestMethod (), arguments .getAfterMethods ());
748750 runConfigMethods (arguments , suite , testResult , teardownConfigMethods );
751+ }
749752
753+ private void runAfterGroupsConfigurations (TestMethodArguments arguments ) {
750754 GroupConfigMethodArguments grpArgs =
751755 new GroupConfigMethodArguments .Builder ()
752756 .forTestMethod (arguments .getTestMethod ())
@@ -795,50 +799,51 @@ public ITestResult registerSkippedTestResult(
795799
796800 private StatusHolder considerExceptions (
797801 ITestNGMethod tm ,
798- ITestResult testresult ,
802+ ITestResult testResult ,
799803 ExpectedExceptionsHolder exceptionsHolder ,
800804 FailureContext failure ) {
801805 StatusHolder holder = new StatusHolder ();
802- holder . status = testresult .getStatus ();
806+ int status = testResult .getStatus ();
803807 holder .handled = false ;
804808
805- Throwable ite = testresult .getThrowable ();
806- if (holder . status == ITestResult .FAILURE && ite != null ) {
809+ Throwable ite = testResult .getThrowable ();
810+ if (status == ITestResult .FAILURE && ite != null ) {
807811
808812 // Invocation caused an exception, see if the method was annotated with @ExpectedException
809813 if (exceptionsHolder != null ) {
810814 if (exceptionsHolder .isExpectedException (ite )) {
811- testresult .setStatus (ITestResult .SUCCESS );
812- holder . status = ITestResult .SUCCESS ;
815+ testResult .setStatus (ITestResult .SUCCESS );
816+ status = ITestResult .SUCCESS ;
813817 } else {
814818 if (isSkipExceptionAndSkip (ite )) {
815- holder . status = ITestResult .SKIP ;
819+ status = ITestResult .SKIP ;
816820 } else {
817- testresult .setThrowable (exceptionsHolder .wrongException (ite ));
818- holder . status = ITestResult .FAILURE ;
821+ testResult .setThrowable (exceptionsHolder .wrongException (ite ));
822+ status = ITestResult .FAILURE ;
819823 }
820824 }
821825 } else {
822- handleException (ite , tm , testresult , failure .count ++);
826+ handleException (ite , tm , testResult , failure .count ++);
823827 holder .handled = true ;
824- holder . status = testresult .getStatus ();
828+ status = testResult .getStatus ();
825829 }
826- } else if (holder . status != ITestResult .SKIP && exceptionsHolder != null ) {
830+ } else if (status != ITestResult .SKIP && exceptionsHolder != null ) {
827831 TestException exception = exceptionsHolder .noException (tm );
828832 if (exception != null ) {
829- testresult .setThrowable (exception );
830- holder . status = ITestResult .FAILURE ;
833+ testResult .setThrowable (exception );
834+ status = ITestResult .FAILURE ;
831835 }
832836 }
837+ holder .originalStatus = testResult .getStatus ();
838+ holder .status = status ;
833839 return holder ;
834840 }
835841
836- private static int computeTestStatusComparingTestResultAndStatusHolder (
837- ITestResult testResult , StatusHolder holder , boolean wasResultUnaltered ) {
838- if (wasResultUnaltered ) {
839- return holder .status ;
842+ private static void updateStatusHolderAccordingToTestResult (
843+ ITestResult testResult , StatusHolder holder ) {
844+ if (holder . originalStatus != testResult . getStatus () ) {
845+ holder .status = testResult . getStatus () ;
840846 }
841- return testResult .getStatus ();
842847 }
843848
844849 private class MethodInvocationAgent {
0 commit comments