Add JUnit 5 @RepeatedTest demo project

Initial commit of a Maven project demonstrating JUnit 5's @RepeatedTest annotation. Includes example tests for basic repetition, custom display names, metadata injection, lifecycle management, and failure thresholds. Project files include .gitignore, README, pom.xml, and test classes under src/test/java/com/ankurm/tutorials/junit/repeated.
This commit is contained in:
Ankur
2025-12-31 17:38:29 +05:30
commit 5ed079dff3
8 changed files with 188 additions and 0 deletions

27
.gitignore vendored Normal file
View File

@@ -0,0 +1,27 @@
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*
#IntelliJ IDEA
.idea/

37
RepeatedTest/README.md Normal file
View File

@@ -0,0 +1,37 @@
# JUnit 5 @RepeatedTest Demonstration
This project demonstrates the usage of JUnit 5's `@RepeatedTest` annotation to improve test reliability and handle flaky tests.
## Concepts Covered
The code examples in `src/test/java/com/ankurTutorials/junit/repeated` cover the following concepts:
1. **Basic Repetition**: Repeating a test a specific number of times.
- File: `ReliabilityTest.java`
2. **Custom Display Names**: Configuring formatted names for each repetition for better reporting in CI/CD.
- File: `CustomNameTest.java`
3. **Metadata Injection**: Using `RepetitionInfo` to access the current repetition index and total count within the test.
- File: `MetadataTest.java`
4. **Lifecycle Management**: Understanding how `@BeforeEach` and `@AfterEach` interact with repeated tests (they run for *each* repetition).
- File: `LifecycleTest.java`
5. **Failure Thresholds**: Using the `failureThreshold` attribute (JUnit 5.10+) to stop execution early if a certain number of failures occur.
- File: `FlakyServiceTest.java`
## Prerequisites
- Java 17 or higher
- Maven 3.6+
## How to Run
To run all tests, execute the following command in the project root:
```bash
mvn test
```
To run a specific test class:
```bash
mvn -Dtest=BasicUsageTest test
```

36
RepeatedTest/pom.xml Normal file
View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ankurTutorials</groupId>
<artifactId>repeated-test-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.version>5.10.1</junit.version>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.2.3</version>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,14 @@
package com.ankurm.tutorials.junit.repeated;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.RepeatedTest;
public class CustomNameTest {
@RepeatedTest(value = 3, name = "{displayName} - Run {currentRepetition}/{totalRepetitions}")
@DisplayName("Critical API Integration")
void customNameTest() {
System.out.println("Verifying external API stability...");
// Logic to verify external API stability
}
}

View File

@@ -0,0 +1,21 @@
package com.ankurm.tutorials.junit.repeated;
import org.junit.jupiter.api.RepeatedTest;
import static org.junit.jupiter.api.Assertions.fail;
public class FlakyServiceTest {
// If 2 out of the 10 repetitions fail, JUnit stops further executions.
// Note: failureThreshold requires JUnit 5.10+
@RepeatedTest(value = 10, failureThreshold = 2)
void flakyServiceTest() {
// Simulating intermittent failure (mostly passing)
// Using a high failure rate here to demonstrate the threshold quickly if run multiple times
// or effectively showing it passes mostly.
// Let's make it 30% failure chance.
if (Math.random() < 0.3) {
fail("Simulated random failure");
}
System.out.println("Test passed");
}
}

View File

@@ -0,0 +1,24 @@
package com.ankurm.tutorials.junit.repeated;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.RepetitionInfo;
public class LifecycleTest {
@BeforeEach
void setUp(RepetitionInfo info) {
System.out.println("BeforeEach: Setting up for repetition " + info.getCurrentRepetition());
}
@RepeatedTest(3)
void lifecycleTest() {
System.out.println("Executing test logic...");
}
@AfterEach
void tearDown(RepetitionInfo info) {
System.out.println("AfterEach: Cleaning up after repetition " + info.getCurrentRepetition());
}
}

View File

@@ -0,0 +1,16 @@
package com.ankurm.tutorials.junit.repeated;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.RepetitionInfo;
class MetadataTest {
@RepeatedTest(3)
void testWithMetadata(RepetitionInfo info) {
int current = info.getCurrentRepetition();
int total = info.getTotalRepetitions();
// Log progress or vary data inputs based on 'current'
System.out.println("Processing batch: " + current + " of " + total);
}
}

View File

@@ -0,0 +1,13 @@
package com.ankurm.tutorials.junit.repeated;
import org.junit.jupiter.api.RepeatedTest;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class ReliabilityTest {
@RepeatedTest(5) // The test will run exactly 5 times
void simpleRepeatTest() {
System.out.println("Executing test...");
assertTrue(true);
}
}