← Назад к вопросам

Что такое параметризованные тесты?

2.0 Middle🔥 201 комментариев
#Тестирование

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Параметризованные тесты

Параметризованные тесты — это тестовые методы, которые запускаются несколько раз с разными входными данными. Это позволяет проверить один и тот же код при различных условиях без дублирования кода теста.

Назначение и преимущества

Основное назначение параметризованных тестов:

  • Избежание дублирования кода: Один тест вместо множества похожих методов
  • Полнота тестирования: Проверка разных edge cases и сценариев
  • Читаемость: Наглядное отображение всех тестовых случаев
  • Поддерживаемость: Легче добавлять новые тестовые данные

Реализация в JUnit 5

В JUnit 5 параметризованные тесты реализуются с помощью аннотаций @ParameterizedTest и различных источников данных:

1. @ValueSource

Для простых значений одного типа:

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

class CalculatorTest {
    @ParameterizedTest
    @ValueSource(ints = {1, 2, 3, 4, 5})
    void testIsPositive(int number) {
        assertTrue(number > 0);
    }
}

2. @CsvSource

Для нескольких параметров через CSV:

@ParameterizedTest
@CsvSource({
    "2, 2, 4",
    "3, 3, 6",
    "5, 0, 5",
    "-1, 1, 0"
})
void testAdd(int a, int b, int expected) {
    Calculator calc = new Calculator();
    assertEquals(expected, calc.add(a, b));
}

3. @CsvFileSource

Для больших наборов данных из CSV файла:

@ParameterizedTest
@CsvFileSource(resources = "/test-data.csv")
void testFromFile(String input, String expected) {
    assertEquals(expected, processInput(input));
}

4. @MethodSource

Для сложной логики генерации тестовых данных:

@ParameterizedTest
@MethodSource("provideTestData")
void testWithComplexData(String input, int expectedLength) {
    assertEquals(expectedLength, input.length());
}

static Stream<Arguments> provideTestData() {
    return Stream.of(
        Arguments.of("hello", 5),
        Arguments.of("world", 5),
        Arguments.of("test", 4),
        Arguments.of("", 0)
    );
}

5. @EnumSource

Для перебора значений enum:

enum Status { ACTIVE, INACTIVE, PENDING }

@ParameterizedTest
@EnumSource(Status.class)
void testAllStatuses(Status status) {
    assertNotNull(status);
}

Пример: Валидация email адресов

class EmailValidatorTest {
    private EmailValidator validator = new EmailValidator();
    
    @ParameterizedTest(name = "{0} is valid: {1}")
    @CsvSource({
        "user@example.com, true",
        "invalid.email@, false",
        "@example.com, false",
        "user@domain, true",
        "user+tag@example.co.uk, true"
    })
    void testEmailValidation(String email, boolean expected) {
        assertEquals(expected, validator.isValid(email));
    }
}

Параметризованные тесты в JUnit 4

До JUnit 5, для параметризации использовались @RunWith(Parameterized.class):

@RunWith(Parameterized.class)
public class ParameterizedTestJUnit4 {
    @Parameterized.Parameters
    public static Collection<Object[]> data() {
        return Arrays.asList(new Object[][] {
            { 2, 4 },
            { 3, 6 },
            { 5, 10 }
        });
    }
    
    private int input;
    private int expected;
    
    public ParameterizedTestJUnit4(int input, int expected) {
        this.input = input;
        this.expected = expected;
    }
    
    @Test
    public void testMultiply() {
        assertEquals(expected, input * 2);
    }
}

Лучшие практики

  1. Выбери подходящий источник данных: Для простых случаев используй @ValueSource, для сложных — @MethodSource
  2. Добавь подробные имена тестов: Используй параметр name в @ParameterizedTest для логирования
  3. Группируй связанные случаи: Организуй тестовые данные логично
  4. Не переусложняй: Если тест становится сложным для понимания, может быть лучше отдельные методы
  5. Используй edge cases: Включай граничные значения, пустые строки, null и т.д.

Сравнение с обычными тестами

// ❌ Без параметризации - код дублируется
@Test
void test2Plus2() { assertEquals(4, add(2, 2)); }

@Test
void test3Plus3() { assertEquals(6, add(3, 3)); }

@Test
void test5Plus0() { assertEquals(5, add(5, 0)); }

// ✅ С параметризацией - один метод
@ParameterizedTest
@CsvSource({"2, 2, 4", "3, 3, 6", "5, 0, 5"})
void testAdd(int a, int b, int expected) {
    assertEquals(expected, add(a, b));
}

Параметризованные тесты — это мощный инструмент для создания более надёжного и поддерживаемого кода тестов, позволяющий одним методом охватить множество сценариев.