Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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

This comment has been minimized.

Copy link
Owner Author

commented Jul 1, 2015

Usage:

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

This comment has been minimized.

Copy link

commented Jul 1, 2015

Nice work man. 👍

@plackemacher

This comment has been minimized.

Copy link

commented Jul 1, 2015

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

This comment has been minimized.

Copy link

commented Jul 22, 2015

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

This comment has been minimized.

Copy link

commented Jul 22, 2015

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

commented Jan 11, 2019

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
You can’t perform that action at this time.