TestNG can automatically re-run failed tests via a custom IRetryAnalyzer, so intermittent (flaky) failures get another attempt before being reported as failed. JUnit 5 does this via extensions or the RetryingTest third-party support.
In TestNG you implement IRetryAnalyzer's retry(ITestResult) to return true up to N times, and attach it with @Test(retryAnalyzer = MyRetry.class) or globally via a listener/IAnnotationTransformer. A passing retry is reported as passed (sometimes flagged). This absorbs irreducible environmental noise, but — like Cypress retries — it must not MASK real, reproducible bugs. JUnit 5 has no built-in retry; you use an extension (e.g. @RepeatedTest is different; retry needs a custom TestExecutionExceptionHandler or a library). Best practice: fix root causes (waits, stable selectors, isolated data) and use retries sparingly as a safety net.
A flaky UI test tagged with a retry analyzer (2 retries) stops failing the nightly build on transient network blips, while the team tracks and fixes the underlying wait/selector issues rather than relying on retries.
Your CI is only green because failed tests retry 3 times. Why is that risky and what's the correct long-term action?