Lesson 6 / 25
Parameterized Tests
Run one test with many inputs using value, CSV, enum and method sources.
One test, many cases
When the same behaviour must hold for many inputs, @ParameterizedTest runs one test method once per set of arguments, reporting each case separately. Sources supply the arguments. @ValueSource provides a single literal per invocation (ints, strings and so on). @CsvSource provides several columns per row inline ("99999, true, 9900"), and @CsvFileSource reads them from a file. @EnumSource runs once per enum constant, optionally filtered. @MethodSource refers to a static factory method returning a Stream<Arguments> for complex objects. @NullSource, @EmptySource and @NullAndEmptySource add edge cases. Customise readable case names with name = "{index}: total {0} -> fee {2}". Parameterised tests are ideal for boundary values (just below, at and just above a threshold), validation rules and conversions, and they replace copy-pasted tests that differ only in their data.
Boundary values with CSV and method sources
Each row is reported as its own test case.
class ShippingCalculatorParamTest {
private final ShippingCalculator calc = new ShippingCalculator();
@ParameterizedTest(name = "total {0}, express {1} -> fee {2}")
@CsvSource({
"0, false, 4900",
"99999, false, 4900",
"99999, true, 9900",
"100000, false, 0",
"100000, true, 0"
})
void feeDependsOnTotalAndSpeed(long totalPaise, boolean express, long expectedFee) {
assertEquals(expectedFee, calc.feePaise(totalPaise, express));
}
@ParameterizedTest
@NullAndEmptySource
@ValueSource(strings = {" ", "not-an-email", "a@"})
void invalidEmailsAreRejected(String email) {
assertFalse(EmailValidator.isValid(email));
}
static Stream<Arguments> coupons() {
return Stream.of(
Arguments.of("FESTIVE10", 100_000, 10_000),
Arguments.of("FLAT50", 20_000, 5_000));
}
@ParameterizedTest
@MethodSource("coupons")
void couponDiscounts(String code, long total, long expectedDiscount) {
assertEquals(expectedDiscount, Coupons.discountPaise(code, total));
}
}Test the boundaries
Bugs cluster at edges: 99,999 versus 100,000 paise, empty strings, zero quantities, the last day of the month. Parameterised tests make it cheap to cover each edge explicitly.
Quick check: Which source runs a parameterized test once per row of inline comma-separated values?
- @CsvSource
- @ValueSource
- @EnumSource
- @NullSource
Answer
@CsvSource — @CsvSource supplies multiple arguments per invocation from inline CSV rows.