JavaRush /Курсы /JSP & Servlets /Параметризованные тесты в Junit

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

JSP & Servlets
3 уровень , 4 лекция
Открыта

5.1 Аннотация @ParameterizedTest

Иногда просто хочется вызвать тест несколько раз с различными параметрами: разные значения, разные входные параметры, разные имена пользователей. JUnit стремится упростить тебе жизнь, поэтому на этот случай у него есть такая вещь как параметризированные тесты.

Для использования параметризованных тестов надо добавить еще одну зависимость в ваш pom.xml:

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-params</artifactId>
    <version>5.8.2</version>
    <scope>test</scope>
</dependency>

После чего можем рассмотреть пример:


@ParameterizedTest
@ValueSource(ints = { 1, 2, 3 })
void testMethod(int argument) {
    //test code
}
 
@ParameterizedTest
@ValueSource(ints = { 1, 2, 3 })
void testMethodWithAutoboxing(Integer argument) {
    //test code
}

Каждый тестовый метод вызовется по 3 раза и при каждом вызове в него будет передан очередной параметр. Значения задаются с помощью другой аннотации — @ValueSource. Но о ней нужно рассказать подробнее.

5.2 Аннотация @ValueSource

Аннотация @ValueSource отлично подходит для работы с примитивами и литералами. Просто перечисли значения параметра через запятую и тест будет вызван по одному разу для каждого значения.


@ParameterizedTest
@ValueSource(ints = { 1, 2, 3 })
void testMethodWithAutoboxing(Integer argument) {
    //test code
}

Но есть и минус — эта аннотация не поддерживает null, так что для него нужно будет использовать специальный костыль — @NullSource. Выглядит это так:


@ParameterizedTest
@NullSource
void testMethodNullSource(Integer argument) {
    assertTrue(argument == null);
}

5.3 Аннотация @EnumSource

Также есть специальная аннотация @EnumSource, которая передает в метод все значения определенного Enum’а. Ее применение выглядит так:


enum Direction {
    EAST, WEST, NORTH, SOUTH
}
 
@ParameterizedTest
@EnumSource(Direction.class)
void testWithEnumSource(Direction d) {
    assertNotNull(d);
}

5.4 Аннотация @MethodSource

А как же передавать в качестве параметров объекты? Особенно, если они имеют сложный алгоритм построения. Для этого можно просто указать специальный вспомогательный метод, который будет возвращать список (Stream) из таких значений.

Пример:


@ParameterizedTest
@MethodSource("argsProviderFactory")
void testWithMethodSource(String argument) {
    assertNotNull(argument);
}
 
static Stream<String> argsProviderFactory() {
    return Stream.of("один", "два",  "три");
}

Параметризованные тесты с несколькими аргументами

Конечно вы уже задались вопросом, а что делать, если в метод хочется передать несколько параметров. Для этого есть очень классная аннотация @CSVSource. Она позволяет перечислить значения параметров метода просто через запятую.

Пример:


@ParameterizedTest
@CsvSource({
    "alex, 30, Программист, Работает",
    "brian, 35, Тестировщик, Работает",
	"charles, 40, Менеджер, Пинает"
})
void testWithCsvSource(String name, int age, String occupation, String status) {
	//код метода
}
Комментарии (11)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Андрей Уровень 2 Expert
27 июля 2024
Уже вижу ошибку в @MethodSource("argsProviderFactory"). Статическая функция которая передает аргументы должна возвращать Stream<Arguments> а не Stream<ЧТО УГОДНО>

static Stream<Arguments> argsProviderFactory() {
    return Stream.of(Arguments.of("один"),Arguments.of( "два"), Arguments.of( "три"));
}
Также @MethodSource может передавать несколько параметров!! Для этого перечисляем их в Arguments.of(...)

void testWithMethodSource(String argument1,String argument2,String argument3 ) {
  ....
}
static Stream<Arguments> argsProviderFactory() {
    return Stream.of(Arguments.of("один","два", "три"),Arguments.of("четыре","пять", "шесть"));
}
UPD: см ниже комментарий от Vasya Pupkin
28 ноября 2023
А как же передавать в качестве параметров объекты? Особенно, если они имеют сложный алгоритм построения. Для этого можно просто указать специальный вспомогательный метод, который будет возвращать список (Stream) из таких значений. Скорее не значений, а объектов. Потому, что значения мы же передаем с аннотацией @ValueSource "Csv" обозначает формат данных - CSV (Comma-Separated Values), что переводится как "Значения, разделённые запятыми"
Антон Уровень 111 Expert
23 августа 2022
"Пинает" 😂
Иван Голубев Уровень 108 Expert
10 июля 2022
<dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-params</artifactId> <version>5.8.2</version> <scope>test</scope> </dependency> дополнительно для параметризированных тестов в maven
Jh-007 Уровень 28
22 июня 2022

@ParameterizedTest
@ValueSource(ints = { 1, 2, 3 })
void testMethod(int argument) {
    //test code
}
А как результат проверить? Как писать assert для нескольких значений?
Anonymous #2957882 Уровень 1
12 августа 2022
На примере калькулятора
Роман Уровень 92
10 декабря 2023
тоже появился такой вопрос после прочтения статья. Спасибо, что задали его до меня))
Kate Уровень 14
2 июня 2022
При использовании @MethodSource также можно передавать несколько параметров в тестовый метод через запятую:

@ParameterizedTest
@MethodSource("argsProviderFactory")
void testWithMethodSource(String argument1, String argument2, String argument3) {
    assertNotNull(argument);
}

static Stream<String> argsProviderFactory() {
    return Stream.of("один", "два", “три”);
}
BlackGrizzli Team Уровень 46
9 марта 2023
А рабочий вариант можно !? Чтобы подтвердить ваши слова

   @ParameterizedTest
    @MethodSource("argsProviderTest")
    void testWithMethod(String argument1, String argument2) {
        assertNotNull(argument1);
        assertNotNull(argument2);

    }

    static Stream<String> argsProviderTest() {
        return Stream.of("один", "два");
    }
Оно так не работает
Vasya Pupkin Уровень 2
16 мая 2023
Вот пример из документации:

@ParameterizedTest
@MethodSource("stringIntAndListProvider")
void testWithMultiArgMethodSource(String str, int num, List<String> list) {
    assertEquals(5, str.length());
    assertTrue(num >=1 && num <=2);
    assertEquals(2, list.size());
}

static Stream<Arguments> stringIntAndListProvider() {
    return Stream.of(
        arguments("apple", 1, Arrays.asList("a", "b")),
        arguments("lemon", 2, Arrays.asList("x", "y"))
    );
}
Уровень 51
29 мая 2022
лайк