Статьи

Написание лучших модульных тестов за меньшее время с параметрами Junit

Большинство людей понимают важность и преимущества модульных тестов и то, почему они должны быть в проектах, над которыми вы работаете. Кроме того, большинство людей не любят писать модульные тесты в проектах, над которыми они работают. Конечно, люди из TDD находятся на другом крае зрения, но по моему опыту они — меньшинство в ИТ-индустрии.

Когда дело доходит до меня, хорошо я с большинством людей :-). Я знаю, почему иметь модульные тесты хорошо, и как это улучшит качество кода и проектов. Я знаю, почему вы должны инвестировать в них, однако я не очень рад писать модульные тесты, это не то, что заставляет меня бодрствовать ночью. Я предпочитаю гораздо больше создавать классные программы и решать сложные задачи, чем писать модульные тесты. Вот почему я всегда в поиске вещей, которые могут помочь мне получить больше и лучше модульных тестов, с меньшими затратами работы с моей стороны, так как в итоге у вас должны быть модульные тесты в ваших проектах.

Junit Params может помочь вам написать лучший юнит-тест с меньшими затратами времени.

Почему вы должны заботиться о Junit Params?

Давайте представим, что у нас есть простой класс Person, который имеет имя и фамилию. Бизнес-требование заключается в том, что имя и фамилия не могут быть пустыми или пустыми.

Мы можем получить класс, похожий на этот

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
public class Person {
 
    private final String firstName;
    private final String lastName;
 
    public Person(String first, String last) {
        if(first == null || first.trim().isEmpty() || last == null || last.trim().isEmpty() ) {
            throw new RuntimeException("bad input");
        }
        this.firstName = first;
        this.lastName = last;
    }
 
    public String getFirstName() {
        return firstName;
    }
 
    public String getLastName() {
        return lastName;
    }
}

Следующий шаг — убедиться, что код работает так, как задумано, и что мы учли все возможные случаи.

Конечно, мы хотели бы охватить все эти возможности с помощью модульных тестов, но если вы подумаете об этом, у нас будет много повторяющегося кода, в котором мы проверяем имя для всех возможностей, а затем фамилию, а затем все комбинации и так далее, если мы хотим охватить все крайние случаи. Мы получим гораздо больше кода в модульных тестах, чем код нашей бизнес-логики для этого простого класса.

Давайте посмотрим, как JUnit Params может помочь нам в этом.

Начальная настройка

Чтобы использовать Junit Params, вам просто нужно добавить зависимость, как для любой другой библиотеки

1
2
3
4
5
6
<dependency>
    <groupId>pl.pragmatists</groupId>
    <artifactId>JUnitParams</artifactId>
    <version>1.1.1</version>
    <scope>test</scope>
</dependency>

После этого мы можем начать использовать JUnit Params в наших модульных тестах.

Тесты JUnit с использованием параметров JUnit

Давайте напишем сейчас несколько юнит-тестов с использованием JUnit Params.

Создайте простой тестовый класс PersonTest и добавьте @RunWith ( JUnitParamsRunner.class )

1
2
3
4
@RunWith(JUnitParamsRunner.class)
public class PersonTest {
    .......
}

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

1
2
3
4
@Test(expected = RuntimeException.class)
public void fistNameNull() {
    Person p = new Person(null,"dummyLast");
}

Отличительной особенностью JUnit Params является то, что мы все еще можем писать стандартные модульные тесты и комбинировать их с JUnit Params.

Чтобы использовать параметры JUnit в этом модульном тесте, мне просто нужно добавить @Parameters с соответствующими значениями, и тогда это будет выглядеть примерно так

1
2
3
4
5
@Test(expected = RuntimeException.class)
@Parameters({ ""," " ,"  ", "   "})
public void fistNameParamaters(String param) {
    Person p = new Person(param,"dummyLast");
}

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

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

Передача параметров в несколько входных параметров

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

1
2
3
4
5
6
7
8
@Test(expected = RuntimeException.class)
@Parameters({ " " ,"    ", // firstName, lastName
            "  ","",
            "   ", "  ",
            "    "," "})
public void fistNameLastNameParamaters(String first, String last) {
    Person p = new Person(first, last);
}

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

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

Передача параметров в несколько входных параметров в удобной для пользователя форме

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

1
2
3
4
5
@Test(expected = RuntimeException.class)
@Parameters({ " |    " , "  |", "   |  ", "    | "})
public void fistNameLastNameParamaters2(String first, String last) {
    Person p = new Person(first, last);
}

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

Использование не строковых значений в качестве входных параметров

До сих пор все параметры были строки. Что если наш входной параметр не является строкой или чем-то, что легко конвертировать из / в строку, например, нулевое значение.

В этом случае мы можем использовать именованный параметр

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
@Test(expected = RuntimeException.class)
@Parameters(named = "emptyStrings")
public void namedParamaters(String first, String last) {
    Person p = new Person(first, last);
}
 
@NamedParameters("emptyStrings")
private Object[] emptyStrings() {
    return new Object[]{
            new Object[]{null, ""},
            new Object[]{"", null},
            new Object[]{" ", "  "},
            new Object[]{"   ", " "}
    };
}

Ссылка

Примеры кода, упомянутые в этом посте, можно найти по этому URL

Опубликовано на Java Code Geeks с разрешения Владимира Деяновича, партнера нашей программы JCG . См. Оригинальную статью здесь: Написание лучших модульных тестов за меньшее время с параметрами Junit

Мнения, высказанные участниками Java Code Geeks, являются их собственными.