repeated
Companion module for JUnit @RepeatedTest (JUnit 5 → 6) on ankurm.com.
What this is
@RepeatedTest and RepetitionInfo are byte-for-byte unchanged between JUnit Jupiter 5.10.1
and 6.1.3 — confirmed here with javap against the real jars, not assumed from a changelog. The
"JUnit 5 → 6" part of this module's story is almost entirely a version-number story: JUnit 6
unified versioning across Platform, Jupiter and Vintage (they all now share one release number,
confirmed against the real maven-metadata.xml for all three artifacts) and raised the minimum
Java version to 17. Nothing about @RepeatedTest itself had to change for that.
What did need fixing is what the previous version of this post got wrong or left out, each verified against a real jar, a real sources jar, or a real run rather than against prose:
{shortDisplayname}is not a real placeholder. There are exactly three:DISPLAY_NAME_PLACEHOLDER,CURRENT_REPETITION_PLACEHOLDER,TOTAL_REPETITIONS_PLACEHOLDER(confirmed viajavaponRepeatedTest.class). Aname()pattern containing the bogus token is accepted at compile time and left completely unresolved at run time — seedocs/output/03-bogus-placeholder-scratch.txt.RepetitionInfocarries four accessors, not two.getFailureCount()andgetFailureThreshold()have been on the interface since JUnit 5.10, the same release that addedfailureThreshold()itself.RepetitionInfocan be injected into@BeforeEach/@AfterEach, not only into the@RepeatedTestmethod.- Once
failureThresholdis reached, JUnit skips the remaining repetitions — it does not merely "stop" them, and they are never invoked at all. Seedocs/output/07-failure-threshold-skips-remaining.txtfor the real console-tree output showingFailure threshold [2] exceededagainst repetitions 9 and 10.
Self-correction made before this module was finished: the "flaky test detection" use case needs a reproducible failure, not real timing-dependent flakiness, so both demo scratch classes fail deterministically on fixed repetition numbers (4 and 8 of 10) rather than relying on actual race conditions. Both were run for real, their output captured, and then deleted — they were never meant to be part of the permanent green suite.
Versions
| Dependency | Version | Verified against |
|---|---|---|
| JUnit Jupiter | 6.1.3 | maven-metadata.xml (latest/release), matching junit-bom and junit-platform-launcher — JUnit 6's unified versioning |
| AssertJ | 3.27.7 | maven-metadata.xml, <release> |
| Maven Surefire | 3.6.0 | this module's own build |
| JDK | 25 (Temurin) | java -version, this module's own build |
@RepeatedTest/RepetitionInfo class files are identical (via javap) across 5.10.1 and 6.1.3.
getFailureCount()/getFailureThreshold() are absent in 5.9.3's RepeatedTest.class and present
from 5.10.1 onward — the old post's "introduced in 5.10" claim for failureThreshold itself is
correct; it just never documented these two accessors.
Quickstart
mvn test # 14 tests, 0 failures
Test classes
| Class | What it proves | Captured output |
|---|---|---|
ReliabilityTest |
The smallest @RepeatedTest(5); real default display names resolved through injected TestInfo |
docs/output/01-basic-repetition.txt |
CustomNameTest |
A custom name() pattern built from the three real placeholders |
docs/output/02-custom-display-name.txt |
MetadataTest |
All four RepetitionInfo accessors, including the two the old post never covered |
docs/output/04-repetition-info-metadata.txt |
LifecycleTest |
@BeforeAll/@AfterAll (once) vs @BeforeEach/@AfterEach (per repetition), plus RepetitionInfo injected into @BeforeEach/@AfterEach |
docs/output/05-lifecycle-order.txt |
Captured output
| File | Contents |
|---|---|
docs/output/00-full-test-run.txt |
mvn test — all 4 committed classes, 14 tests, 0 failures |
docs/output/01-basic-repetition.txt |
ReliabilityTest — real default display names |
docs/output/02-custom-display-name.txt |
CustomNameTest — real custom display names |
docs/output/03-bogus-placeholder-scratch.txt |
Scratch run proving {shortDisplayname} is not a real placeholder and resolves to literal text |
docs/output/04-repetition-info-metadata.txt |
MetadataTest — all four RepetitionInfo accessors across 3 repetitions |
docs/output/05-lifecycle-order.txt |
LifecycleTest — real call order and totals across 3 repetitions |
docs/output/06-flaky-detected.txt |
Scratch run: no failureThreshold set — all 10 repetitions run even though 2 fail |
docs/output/07-failure-threshold-skips-remaining.txt |
Scratch run: failureThreshold = 2 — repetitions 9 and 10 skipped after the 2nd failure |
docs/output/03, 06 and 07 come from scratch classes (ScratchPlaceholderTest,
FlakyDetectionDemoTest, FailureThresholdStopsRemainingDemoTest) that were written, run once
for real evidence, and then deleted — they are not part of the committed suite, which stays green
at 14/14. Re-run scripts/run-all.sh to see exactly how each transcript was produced.
What's sourced from documentation, not run here
The JUnit 6.0.0 release notes facts quoted in the post (minimum Java 17, Vintage deprecated,
junit-platform-runner/junit-platform-jfr removal, MethodOrderer.Alphanumeric removal,
@CsvSource moving to FastCSV) are quoted from the official JUnit 6.0.0 release notes, not
exercised in this module — none of them touch @RepeatedTest or RepetitionInfo directly.
Everything else above was compiled, run, or pulled directly from a real jar in this sitting.