Введение в JUnitParams

Введение в JUnitParams

1. обзор

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

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

2. Maven Dependency

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


    pl.pragmatists
    JUnitParams
    1.1.0

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

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::

@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));
    }

}

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

Первое, что мы замечаем, это то, чтоthere is adifferent test runner в аннотации класса -JUnitParamsRunner.

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

Если мы запустим тест с помощью Maven, мы увидим, чтоwe are running four test cases and not a single one. Вывод будет похож на следующее:

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

Results :

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

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

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

  • Непосредственно в аннотации@Parameters (используется в примере выше)

  • Использование именованного метода тестирования, определенного в аннотации

  • Использование метода, сопоставленного с именем метода теста

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

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

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

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

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

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

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

5.2. Параметр Метод

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

@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 }
    };
}

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

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

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

5.3. Метод сопоставлен по имени метода тестирования

Если мы ничего не укажем в аннотации@Parameters,JUnitParams попытается загрузить метод поставщика тестовых данных на основе имени тестового метода. Имя метода строится как“parametersFor”+ <test method name>:

@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 }
    };
}

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

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

Поскольку этот метод существует, он будет загружать из него данные и запускать тест. If there is no such method matching the required name, the test fails, как в приведенном выше примере.

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

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

@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 },
        };
    }
}

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

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

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

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

Допустим, у нас есть CSV-файл с параметрами тестаJunitParamsTestParameters.csv:

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

Теперь посмотрим, какthis file can be used to load test parameters в тестовом методе:

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

    assertEquals(expectedValue, serviceUnderTest.safeAdd(a, b));
}

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

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

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

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

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