Skip to content

Instantly share code, notes, and snippets.

@JakeWharton
Last active August 31, 2023 15:47
Show Gist options
  • Star 49 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save JakeWharton/7fe7deb1f7f4a795c120 to your computer and use it in GitHub Desktop.
Save JakeWharton/7fe7deb1f7f4a795c120 to your computer and use it in GitHub Desktop.
Got flaky tests? Shampoo them away with a quick JUnit rule. Apache 2.
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
/** Got flaky tests? Shampoo them away. */
public final class ShampooRule implements TestRule {
private final int iterations;
public ShampooRule(int iterations) {
if (iterations < 1) throw new IllegalArgumentException("iterations < 1: " + iterations);
this.iterations = iterations;
}
@Override public Statement apply(final Statement base, Description description) {
return new Statement() {
@Override public void evaluate() throws Throwable {
for (int i = 0; i < iterations; i++) {
base.evaluate();
}
}
};
}
}
@JakeWharton
Copy link
Author

Usage:

@Rule public final TestRule shampoo = new ShampooRule(1000);

@donnfelker
Copy link

Nice work man. 👍

@plackemacher
Copy link

Won't this run the test multiple times, even if it succeeds the first time?

This should fix that:

for (int i = 1; i <= iterations; i++) {
  try {
    base.evaluate();
    break;
  } catch (Throwable e) {
    if (i == iterations) {
      throw e;
    }
  }
}

Or maybe I'm thinking of this rule's purpose a bit differently...

@jacobras
Copy link

Won't this run the test multiple times, even if it succeeds the first time?
Yes, but that is exactly what this rule is meant for: to run a test x (iterations) number of times to make sure it is a stable test.

@jacobras
Copy link

Won't this run the test multiple times, even if it succeeds the first time?

Yes, but that is exactly what this rule is meant for: to run a test x (iterations) number of times to make sure it is a stable test.

@avram
Copy link

avram commented Jul 31, 2015

@JakeWharton-- Mind putting a license block on this? It's pretty useful but probably ought to have an unambiguous statement of license.

@patrickjh
Copy link

Hey man,

I appreciate you posting this. I took it a step further and made a @retries annotation you can add to your test methods directly.

Example:

@test
@retries(3)
public void someTestMethod() {

}

Works with Android custom test runner. Thought it might help anybody who also happens along here. Link:

https://gist.github.com/patrickjh/a65505d53e25e5816b31bb44cbb0e492

Hope that helps someone who comes across this post like I did!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment