This rule raises an issue when at least 3 test methods could be refactored into a single parameterized test with less than 4 parameters.
When multiple tests differ only by a few hardcoded values, they should be refactored into a single parameterized test. This reduces duplication, makes the tests easier to read, and lowers the risk of introducing bugs when the test logic needs to change.
Parameterized tests are supported by most testing frameworks.
The right balance still needs to be found. There is little value in parameterizing tests when the resulting test becomes significantly more complex than the original versions.
with JUnit 5
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
public class AppTest
{
@Test
void test_not_null1() { // Noncompliant. The 3 following tests differ only by one hardcoded number.
setupTax();
assertNotNull(getTax(1));
}
@Test
void test_not_null2() {
setupTax();
assertNotNull(getTax(2));
}
@Test
void test_not_nul3l() {
setupTax();
assertNotNull(getTax(3));
}
@Test
void testLevel1() { // Noncompliant. The 3 following tests differ only by a few hardcoded numbers.
setLevel(1);
runGame();
assertEquals(playerHealth(), 100);
}
@Test
void testLevel2() { // Similar test
setLevel(2);
runGame();
assertEquals(playerHealth(), 200);
}
@Test
void testLevel3() { // Similar test
setLevel(3);
runGame();
assertEquals(playerHealth(), 300);
}
}
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
public class AppTest
{
@ParameterizedTest
@ValueSource(ints = {1, 2, 3})
void test_not_null(int arg) {
setupTax();
assertNotNull(getTax(arg));
}
@ParameterizedTest
@CsvSource({
"1, 100",
"2, 200",
"3, 300",
})
void testLevels(int level, int health) {
setLevel(level);
runGame();
assertEquals(playerHealth(), health);
}
}