Retry a Failed Testcases multiple times before reporting failure

Use Case:
While running automation suite, you may want to rerun a failed testcase multiple times before reporting failure because of what so ever reason(mainly because of uncertain behaviour by application because of latency or other aspect).
If you want to rerun all failed testcase than read this.

Approach:
We will see three approaches using TestNG, using JUnit and Using maven surefire plugin(and JUnit 4.0+).
1. Using TestNG
TestNG provides IRetryAnalyzer interface, which has a method retry which returns boolean value. So if you override this method by implementing this interface, provide it as retryAnalyzer attribute of @Test annotation, TestNG will decides based on value return by overridden method whether to retry a failed test or not.
Let's first Implement IRetryAnalyzer

import org.testng.IRetryAnalyzer;
import org.testng.ITestResult;

public class RetryAnalyzer implements IRetryAnalyzer  { 
private int count = 0; 
private int maxCount = 4; // set your count to re-run test

	@Override 
	public boolean retry(ITestResult result) { 
	        if(count < maxCount) {                     
	            count++;                                    
	            return true; 
	        } 
	        return false; 
	}
}
Here you can see that retry method will return true until count is less than maxCount. Now we need to pass RetryAnalyzer class as parameter to retryAnalazer parameter of @Test Annotation.
import org.testng.annotations.Test;
import org.testng.Assert;

public class testngTest {
    @Test(retryAnalyzer=RetryAnalyzer.class)
    public void thisAlwaysPasses() {
    	Assert.fail();
    }

    @Test
    public void thisIsAnotherTest() {
    }
    
    @Test
    public void thisIsAlsoAnotherTest() {
    }
}
so If test thisAlwaysPasses fails, It will be retried until retry method returns true. Now as a result of retry you will get get test result something like this
Default suite
Total tests run: 7, Failures: 5, Skips: 0
Retries are not identified separately here. and even though we have only 3 test methods, gives total tests run including retry as 7. which may not be desired result sometimes. In that case you can write a listener class as discussed in following stack overflow QA http://stackoverflow.com/questions/13131912/testng-retrying-failed-tests-doesnt-output-the-correct-test-results

2. Using JUnit
You can achieve similar behaviour in JUnit using TestRule.

What is TestRule?(@Rule Annotation)
TestRule provides a powerful way to control your test, testRule gives you hold of your test and surrounding before and after methods as a base And you can perform any before/after task or control result as per your desire.

Here we will implement TestRule interface, which provides apply method which supplies your test method and surrounding after/before test methods as a base statement. so you need to override this apply method and change your statement.
public class JUnitRetry implements TestRule { 
    @Override
	public Statement apply(Statement base, Description description) { 
		//statement is a private method which will return a new statement 
		//here Statement is taken as abstract for your test which includes test method and before/after methods )
		return statement(base, description); 
	} 									
									
So now let's see how to create a new Statement
private Statement statement(final Statement base, final Description description) { 
	return new Statement() { 
		@Override 
		public void evaluate() throws Throwable { 
			Throwable caughtThrowable = null; 

			// implement retry logic here 
			for (int i = 0; i < retryCount; i++) { 
				try { 
					base.evaluate(); 
					return; 
				} catch (Throwable t) { 
					caughtThrowable = t; 
					System.err.println(description.getDisplayName() + ": run " + (i+1) + " failed"); 
				} 
			} 
			System.err.println(description.getDisplayName() + ": giving up after " + retryCount + " failures"); 
			throw caughtThrowable; 
		} 
	}; 
}
As you can see here we are just creating an anonymous Statement object and overriding evaluate method, which will evaluate base statement supplied in apply method and do some additional task( here, evaluate base test again on failure).
Retry logic is also very elegant. It is catching any exception during test run, which indicates failure and rerun it until a particular retry count is reached or test succeeds. And if exception is being thrown in last run as well, then it only it is thrown. so only latest exception will be reported and not all during rerun.
As we want retryCount as something configurable, it needs to be defined as class variable and initialized using constructor. Full class will look something as following:
import org.junit.rules.TestRule; 
import org.junit.runner.Description; 
import org.junit.runners.model.Statement; 

public class JUnitRetry implements TestRule { 

	private int retryCount; 

	public JUnitRetry(int retryCount) { 
		this.retryCount = retryCount; 
	} 

	@Override
	public Statement apply(Statement base, Description description) { 
		return statement(base, description); 
	} 

	private Statement statement(final Statement base, final Description description) { 
		return new Statement() { 
			@Override 
			public void evaluate() throws Throwable { 
				Throwable caughtThrowable = null; 

				// implement retry logic here 
				for (int i = 0; i < retryCount; i++) { 
					try { 
						base.evaluate(); 
						return; 
					} catch (Throwable t) { 
						caughtThrowable = t; 
						System.err.println(description.getDisplayName() + ": run " + (i+1) + " failed"); 
					} 
				} 
				System.err.println(description.getDisplayName() + ": giving up after " + retryCount + " failures"); 
				throw caughtThrowable; 
			} 
		}; 
	} 
}
Now you just want to create object of TestRule under annotation @Rule as following:
										import org.junit.Rule;
import org.junit.Test;
import org.junit.Assert;

public class junitTest {
	@Rule
	public JUnitRetry retry = new JUnitRetry(2);
	
    @Test
    public void thisAlwaysPasses() {
    	Assert.fail();
    }

    @Test
    public void thisIsAnotherTest() {
    }
    
    @Test
    public void thisIsAlsoAnotherTest() {
    }
}
Here JUnit result will not have any impact and will be same as before without any information about retries( Except whatever you log explicitly).

3. Using Maven Surefire Plugin(only with JUnit 4.0):
If you are using Maven and JUnit 4.0 you can achieve this easily by just setting rerunFailingTestsCount > 0 as following:
mvn -Dsurefire.rerunFailingTestsCount=2 test
If you are using Maven from m2eclipse plugin, you need to create new Run configuration and define parameter to be passed along with desired goal.

Tests which are passed after one or more failure will be reported as flaky tests in Report along with details of failed run.
Please refer this for more details.