Files
JUnit_Tutorials/repeated

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 via javap on RepeatedTest.class). A name() pattern containing the bogus token is accepted at compile time and left completely unresolved at run time — see docs/output/03-bogus-placeholder-scratch.txt.
  • RepetitionInfo carries four accessors, not two. getFailureCount() and getFailureThreshold() have been on the interface since JUnit 5.10, the same release that added failureThreshold() itself.
  • RepetitionInfo can be injected into @BeforeEach/@AfterEach, not only into the @RepeatedTest method.
  • Once failureThreshold is reached, JUnit skips the remaining repetitions — it does not merely "stop" them, and they are never invoked at all. See docs/output/07-failure-threshold-skips-remaining.txt for the real console-tree output showing Failure threshold [2] exceeded against 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.