Careeroza
Retry With Backoff
Backoff for Unstable Steps
Some steps talk to slow systems: an OTP mail arriving, a payment sandbox, a search index that updates after a few seconds. Instead of one long sleep, retry with exponential backoff: wait 0.5 s, 1 s, 2 s... up to a limit. Only retry steps that are known to be slow, never assertions on business results.
Example
A fake clock replaces real sleeping so the output is instant and repeatable. The OTP "arrives" after 3.2 seconds:
import java.util.*;
import java.util.function.*;
public class Main {
static long clockMs = 0; // fake clock
static <T> Optional<T> retryWithBackoff(Supplier<Optional<T>> step, int maxAttempts, long firstDelayMs) {
long delay = firstDelayMs;
for (int attempt = 1; attempt <= maxAttempts; attempt++) {
Optional<T> result = step.get();
System.out.printf("t=%5d ms attempt %d -> %s%n", clockMs, attempt, result.isPresent() ? "got it" : "not yet");
if (result.isPresent()) return result;
if (attempt < maxAttempts) {
clockMs += delay; // Thread.sleep(delay) in real code
delay = Math.min(delay * 2, 4000); // double, but cap at 4 s
}
}
return Optional.empty();
}
public static void main(String[] args) {
Supplier<Optional<String>> readOtpFromMailbox =
() -> clockMs >= 3200 ? Optional.of("482913") : Optional.empty();
String otp = retryWithBackoff(readOtpFromMailbox, 6, 500).orElseThrow();
System.out.println("OTP " + otp + " after " + clockMs + " ms");
}
}Output
t= 0 ms attempt 1 -> not yet t= 500 ms attempt 2 -> not yet t= 1500 ms attempt 3 -> not yet t= 3500 ms attempt 4 -> got it OTP 482913 after 3500 ms
Retry in a Real Test
String otp = Retry.withBackoff(() -> mailbox.latestOtpFor("[email protected]"), 6, Duration.ofMillis(500))
.orElseThrow(() -> new AssertionError("OTP mail never arrived"));
otpPage.enter(otp);Note: Retry a step (reading the OTP), not the whole test. A retried test hides the reason; a retried step with a log line shows exactly what was slow.