«1. Обзор

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

Бывают ситуации, когда между несколькими тестами меняются только параметры. Сам JUnit имеет поддержку параметризации, и JUnitParams значительно улучшает эту функциональность.

2. Зависимость от Maven

Чтобы использовать JUnitParams в нашем проекте, нам нужно добавить его в наш pom.xml:

<dependency>
    <groupId>pl.pragmatists</groupId>
    <artifactId>JUnitParams</artifactId>
    <version>1.1.0</version>
</dependency>

Последнюю версию библиотеки можно найти здесь.

3. Тестовый сценарий

Давайте создадим класс, который выполняет безопасное сложение двух целых чисел. Это должно возвращать Integer.MAX_VALUE в случае переполнения и Integer.MIN_VALUE в случае недополнения:

public class SafeAdditionUtil {

    public int safeAdd(int a, int b) {
        long result = ((long) a) + b;
        if (result > Integer.MAX_VALUE) {
            return Integer.MAX_VALUE;
        } else if (result < Integer.MIN_VALUE) {
            return Integer.MIN_VALUE;
        }
        return (int) result;
    }
}

4. Конструирование простого метода тестирования убедитесь, что реализация верна для всех возможных сценариев. JUnitParams предоставляет более одного способа создания параметризованного теста.

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

Теперь давайте посмотрим, чем этот тестовый класс отличается от обычного тестового класса JUnit.

@RunWith(JUnitParamsRunner.class)
public class SafeAdditionUtilTest {

    private SafeAdditionUtil serviceUnderTest
      = new SafeAdditionUtil();

    @Test
    @Parameters({ 
      "1, 2, 3", 
      "-10, 30, 20", 
      "15, -5, 10", 
      "-5, -10, -15" })
    public void whenWithAnnotationProvidedParams_thenSafeAdd(
      int a, int b, int expectedValue) {
 
        assertEquals(expectedValue, serviceUnderTest.safeAdd(a, b));
    }

}

Первое, что мы замечаем, это то, что в аннотации класса есть другой тест-раннер — JUnitParamsRunner.

Переходя к тестовому методу, мы видим, что тестовый метод снабжен аннотацией @Parameters с массивом входных параметров. Он указывает различные сценарии тестирования, которые будут использоваться для тестирования нашего метода обслуживания.

Если мы запустим тест с помощью Maven, мы увидим, что мы запускаем четыре тестовых примера, а не один. Вывод будет примерно таким:

5. Различные типы параметризации методов тестирования

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.baeldung.junitparams.SafeAdditionUtilTest
Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.068 sec 
  - in com.baeldung.junitparams.SafeAdditionUtilTest

Results :

Tests run: 4, Failures: 0, Errors: 0, Skipped: 0

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

Непосредственно в аннотации @Parameters (используется в приведенном выше примере) Использование именованного метода тестирования, определенного в аннотации Использование метода, сопоставленного именем метода тестирования A именованный тестовый класс, определенный в аннотации Использование файла CSV

    Давайте рассмотрим подходы один за другим.

5.1. Непосредственно в аннотации @Parameters

Мы уже использовали этот подход в примере, который мы пробовали. Что нам нужно иметь в виду, так это то, что мы должны предоставить массив строк параметров. В строке параметров каждый параметр отделяется запятой.

Например, массив будет иметь вид { «1, 2, 3», «-10, 30, 20» }, а один набор параметров будет представлен как «1, 2, 3». € .

Ограничение этого подхода заключается в том, что мы можем использовать только примитивы и строки в качестве тестовых параметров. Также нельзя передавать объекты в качестве параметров метода тестирования.

5.2. Parameter Method

Мы можем указать параметры тестового метода, используя другой метод внутри класса. Давайте сначала рассмотрим пример:

Метод тестирования аннотирован относительно метода parametersToAdd(), и он извлекает параметры, запуская указанный метод.

@Test
@Parameters(method = "parametersToTestAdd")
public void whenWithNamedMethod_thenSafeAdd(
  int a, int b, int expectedValue) {
 
    assertEquals(expectedValue, serviceUnderTest.safeAdd(a, b));
}

private Object[] parametersToTestAdd() {
    return new Object[] { 
        new Object[] { 1, 2, 3 }, 
        new Object[] { -10, 30, 20 }, 
        new Object[] { Integer.MAX_VALUE, 2, Integer.MAX_VALUE }, 
        new Object[] { Integer.MIN_VALUE, -8, Integer.MIN_VALUE } 
    };
}

В результате спецификация метода провайдера должна возвращать массив объектов. Если метод с заданным именем недоступен, тестовый пример завершается с ошибкой:

5.3. Метод, сопоставленный именем тестового метода

java.lang.RuntimeException: Could not find method: bogusMethodName so no params were used.

Если мы ничего не указываем в аннотации @Parameters, JUnitParams пытается загрузить метод поставщика тестовых данных на основе имени тестового метода. Имя метода строится как «parametersFor» + \u003cимя метода тестирования\u003e:

В приведенном выше примере имя метода тестирования — whenWithnoParam_shouldLoadByNameAbdSafeAdd().

@Test
@Parameters
public void whenWithnoParam_thenLoadByNameSafeAdd(
  int a, int b, int expectedValue) {
 
    assertEquals(expectedValue, serviceUnderTest.safeAdd(a, b));
}

private Object[] parametersForWhenWithnoParam_thenLoadByNameSafe() {
    return new Object[] { 
        new Object[] { 1, 2, 3 }, 
        new Object[] { -10, 30, 20 }, 
        new Object[] { Integer.MAX_VALUE, 2, Integer.MAX_VALUE }, 
        new Object[] { Integer.MIN_VALUE, -8, Integer.MIN_VALUE } 
    };
}

Поэтому, когда тестовый метод выполняется, он ищет метод поставщика данных с именем parametersForWhenWithnoParam_shouldLoadByNameAbdSafeAdd().

«Поскольку этот метод существует, он загрузит из него данные и запустит тест. Если нет такого метода, соответствующего требуемому имени, тест завершается неудачей, как в приведенном выше примере.

5.4. Именованный тестовый класс, определенный в аннотации

Подобно тому, как мы ссылались на метод поставщика данных в предыдущем примере, мы можем обратиться к отдельному классу, чтобы предоставить данные для нашего теста:

Мы можем иметь любое количество поставщиков тестовых данных в классе, если имя метода начинается с «provide». Если это так, исполнитель выбирает эти методы и возвращает данные.

@Test
@Parameters(source = TestDataProvider.class)
public void whenWithNamedClass_thenSafeAdd(
  int a, int b, int expectedValue) {
 
    assertEquals(expectedValue, serviceUnderTest.safeAdd(a, b));
}
public class TestDataProvider {

    public static Object[] provideBasicData() {
        return new Object[] { 
            new Object[] { 1, 2, 3 }, 
            new Object[] { -10, 30, 20 }, 
            new Object[] { 15, -5, 10 }, 
            new Object[] { -5, -10, -15 } 
        };
    }

    public static Object[] provideEdgeCaseData() {
        return new Object[] { 
            new Object[] { 
              Integer.MAX_VALUE, 2, Integer.MAX_VALUE }, 
            new Object[] { 
              Integer.MIN_VALUE, -2, Integer.MIN_VALUE }, 
        };
    }
}

Если ни один из методов класса не удовлетворяет этому требованию, даже если эти методы возвращают массив объектов, эти методы будут игнорироваться.

5.5. Использование файла CSV

Мы можем использовать внешний файл CSV для загрузки тестовых данных. Это помогает, если количество возможных тестовых случаев достаточно велико или если тестовые наборы часто меняются. Изменения могут быть сделаны, не затрагивая тестовый код.

Предположим, что у нас есть CSV-файл с тестовыми параметрами в виде JunitParamsTestParameters.csv:

Теперь посмотрим, как можно использовать этот файл для загрузки тестовых параметров в тестовый метод:

1,2,3
-10, 30, 20
15, -5, 10
-5, -10, -15

Один ограничением этого подхода является невозможность передачи сложных объектов. Допустимы только примитивы и строки.

@Test
@FileParameters("src/test/resources/JunitParamsTestParameters.csv")
public void whenWithCsvFile_thenSafeAdd(
  int a, int b, int expectedValue) {
 
    assertEquals(expectedValue, serviceUnderTest.safeAdd(a, b));
}

6. Заключение

В этом уроке мы рассмотрели, как мы можем использовать функциональные возможности JUnitParams в двух словах.

Мы также рассмотрели различные подходы, которые библиотека предоставляет нам для предоставления тестовых параметров нашим методам тестирования, что выходит далеко за рамки того, что может сделать сам JUnit.

Как всегда, исходный код можно найти на GitHub.

«