पाठ 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.

त्वरित जाँच: 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.