Unit Test

Модульное тестирование, или юнит-тестирование (unit testing) — процесс в программировании, позволяющий проверить на корректность отдельные модули исходного кода программы.
Идея состоит в том, чтобы писать тесты для каждой нетривиальной функции или метода. Это позволяет достаточно быстро проверить, не привело ли очередное изменение кода к регрессии, то есть к появлению ошибок в уже оттестированных местах программы, а также облегчает обнаружение и устранение таких ошибок.
Общий раздел по Unit Testing
Пример создания Unit-тестов
- JUnit — введение в юнит-тесты. Пример JUnit Hello world
- JUnit — Suite тест. Запуск нескольких тестов с помощью аннотаций @Suite и @RunWith
- Параметризированные тесты в JUnit. Использование @Parameterized.Parameters
- JUnit Listener — добавление слушателей в юнит-тесты

12900 Total Views 1 Views Today
Views: 11 610
Добавить комментарий Отменить ответ
Для отправки комментария вам необходимо авторизоваться.
Подписывайтесь
Нашли ошибку?

Выделите и нажмите CTRL+ENTER 🙂
Copyright © JavaStudy — руководство для java разработчика All Rights Reserved.
Powered by WordPress & Lightning Theme by Vektor,Inc. technology.
Unit тесты в Java. Краткое руководство


Каждая выполненная задача в программировании требует тестирования, потому что от ошибок, как известно, никто не застрахован.
Зачастую на эту процедуру уходит немало времени, даже в простых задачах у новичков. Вы запускаете приложение, вводите данные для проверки и понимаете, что результат не соответствует ожиданиям. Затем вы начинаете выяснять, на каком же этапе произошла ошибка, все это у вас отнимает драгоценные минуты, которые вы могли бы потратить на разработку нового функционала.
А что если ваше приложение большое и в нем много зависящих друг от друга модулей, классов и компонент, и ваша задача — изменить поведение существующего кода, при этом не повредив старое?
В чем смысл Unit-тестов?
Именно для этого придумали юнит тесты, которые дают возможность автоматизировать проверку приложения.
Но ведь на написание тестов тоже уходит время — возразите вы и будете правы. Дело в том, что с ростом вашего приложения это время будет сокращаться, а без тестов ситуация обратная: чем сложнее становится приложение, тем более трудоемким будет его изменение и процесс отслеживания ошибок.
К тому же, не будем забывать, что интеграционное тестирование, которым пользуется большинство «смертных» программистов, требует запуска приложения, а, как известно из основ программирования Java, в Java развертывание и сборка — процесс не самый быстрый.
Помнится мне один банковский проект, в котором я тратил на это 15 минут, но не будем о грустном.
Для того, чтобы проникнуться данной концепцией, предлагаю почитать об экстремальном программировании. А пока давайте рассмотрим, какие инструменты нам предлагает Java для решения этой проблемы, и о том, как создать тест на Java.
Наиболее популярные — JUnit и TestNg, и речь сегодня пойдет о первом. Он является простым и гибким фреймворком для тестирования.
Рекомендуем курс по теме
QA Manual basic
JUnit аннотации и их описание
Пример Unit теста
Для того, чтобы подключить JUnit, нам необходимо добавить dependency в pom.xml, на момент написания статьи самая свежая версия 4.12:
Затем представим, для простоты понимания, что у нас есть класс калькулятор, который может прибавлять и вычитать:
Unit тест для такого класса будет выглядеть так:
- Размещаться данный класс должен в папке test, которая специально создана для хранения тестовых классов.
- Название класса должно соответствовать одной из масок: *Test, Test*, *TestCase для того, чтобы maven surefire plugin смог найти ваш тестовый класс.
- Методы должны иметь возвращаемый тип void в сигнатуре и аннотацию @Test, которая определяет, что метод является тестовым.
- Аннотация @Beforeуказываетна то, что метод будет выполняться перед каждым тестируемым методом.
Также для проверки результата используется специальный проверяемый метод assertEquals, который в нашем случае может принимать сообщение, которое будет показываться при несоответствии фактического и ожидаемого результата, затем второй параметр – фактический результат и третий ожидаемый результат.
Далее открываем терминал, перейдем в папку с нашим проектом и выполним mvn test:
По выводу лога консоли видно, что тесты прошли успешно. Если же мы изменим знак в методе add c + на *, то тест будет failed, и лог будет выглядеть так:
Таким образом, мы сразу видим, какой тест у нас не прошел проверку, и можем начать отладку с нужной точки.
Рекомендуем курс по теме
Java Basic basic
В следующей таблице приведен обзор имеющихся в аннотации JUnit 4.x.
| Аннотация | Описание |
| @Test public void method() public void method() public void method() public static void method() public static void method() | Аннотация @Test определяет что метод method() является тестовым. |
| @Before | Аннотация @Before указывает на то, что метод будет выполнятся перед каждым тестируемым методом @Test. |
| @After | Аннотация @After указываетна то что метод будет выполнятся после каждого тестируемого метода @Test |
| @BeforeClass | Аннотация @BeforeClass указывает на то, что метод будет выполнятся в начале всех тестов, а точней в момент запуска тестов(перед всеми тестами @Test). |
| @AfterClass | Аннотация @AfterClass указывает на то, что метод будет выполнятся после всех тестов. |
| @Ignore | Аннотация @Ignore говорит, что метод будет проигнорирован в момент проведения тестирования. |
| @Test (expected = Exception.class) | (expected = Exception.class) — указывает на то, что в данном тестовом методе вы преднамеренно ожидается Exception. |
| @Test (timeout=1000) | (timeout=1000) — указывает, что тестируемый метод не должен занимать больше чем 1 секунду. |
Проверяемые методы (основные)
| Метод | Описание |
| fail(String) | Указывает на то что бы тестовый метод завалился при этом выводя текстовое сообщение. |
| assertTrue([message], boolean condition) | Проверяет, что логическое условие истинно. |
| assertsEquals([String message], expected, actual) | Проверяет, что два значения совпадают. Для массивов проверяются ссылки, а не содержание массивов. |
| assertNull([message], object) | Проверяет, что объект является пустым null. |
| assertNotNull([message], object) | Проверяет, что объект не является пустым null. |
| assertSame([String], expected, actual) | Проверяет, что обе переменные относятся к одному объекту. |
| assertNotSame([String], expected, actual) | Проверяет, что обе переменные относятся к разным объектам. |
Также я прикрепил пример с ООП моделью компании, в которой подсчитываются затраты на зарплату для сотрудников по компании и департаменту.
Основные методы покрыты unit тестами, код размещен тут.
Причины тестирования — Java: Автоматическое тестирование
Какую главную задачу должны решать тесты? Этот вопрос невероятно важен. Ответ на него даёт понимание того, как правильно писать тесты и как писать их не нужно.
Представьте, что вы написали метод StringUtils.capitalize(text) , который делает заглавной первую букву переданной строки:
StringUtils.capitalize("hello"); // "Hello"
Вот один из вариантов его реализации:
class StringUtils public static String capitalize(String text) return text.substring(0, 1).toUpperCase() + text.substring(1); > >
Что мы делаем после написания метода? Проверяем, как он работает. Например, пишем простейшую программу и пытаемся вызвать этот метод с различными аргументами:
System.out.println(StringUtils.capitalize("hello")); // => "Hello" System.out.println(StringUtils.capitalize("how are you")); // => "How are you"
Таким нехитрым способом убеждаемся, что метод работает. По крайней мере для тех аргументов, которые мы передали в него. Если во время проверки заметили ошибки, то исправляем метод и повторяем всё заново.
Фактически, весь этот процесс и есть тестирование. Но не автоматическое, а ручное. Задача такого тестирования — убедиться, что код работает как надо. И нам совершенно без разницы, как конкретно реализован этот метод. Это и есть главный ответ на вопрос, заданный в начале урока.
Тесты проверяют, что код (или приложение) работает корректно. И не заботятся о том, как конкретно написан код, который они проверяют.
Автоматические тесты
Всё, что требуется от автоматических тестов — повторить проверки, которые мы выполняли, делая ручное тестирование. Для этого достаточно старого доброго if и исключений.
Даже если вы не знакомы с исключениями, ничего страшного. В этом курсе достаточно знать две вещи: для чего они нам нужны и какой у них синтаксис. До сих пор в курсах Хекслета вы встречались с ошибками, которые возникают непроизвольно: вызов несуществующего метода, обращение к несуществующей константе и так далее. Но ошибки можно порождать самостоятельно с помощью исключений, что необходимо для нашей ситуации. В Java есть специальный тип исключений, который принято «пробрасывать» при возникновении ошибок в тестах. Они называются AssertionError , что в дословном переводе означает «ошибка утверждения», т.е. вы в тестах что-то утверждали и, если это утверждение оказалось ошибочным, то пробрасывается AssertionError . Исключения создаются такой конструкцией:
// Дословно: выбросить новую ошибку // Исключения бросают throw new AssertionError("описание исключения"); // Код, следующий за этим выражением, не выполнится, а сама программа завершится с ошибкой System.out.println("nothing");
class StringUtilsTest public static void testCapitalize() // Если результат метода не равен ожидаемому значению if (!"Hello".equals(StringUtils.capitalize("hello"))) // Выбрасываем исключение и завершаем выполнение теста throw new AssertionError("Метод работает неверно!"); > > >
Теперь для запуска теста вам достаточно лишь вызвать метод testCapitalize() в вашем методе main и выполнить программу.
Из примера выше видно, что тесты — это точно такой же код, как и любой другой. Он подчиняется тем же правилам, например, стандартам кодирования. А ещё он может содержать ошибки. Но это не значит, что надо писать тесты на тесты. Избежать всех ошибок невозможно, да и не нужно, иначе стоимость разработки стала бы неоправданно высокой. Обнаруженные ошибки в тестах исправляются, и жизнь продолжается дальше 😉
В коде, тесты складывают в директорию src/test:
Структура этой директории, обычно, повторяет структуру исходного кода.
Как пишутся тесты
Тесты — это не магия. Нам, как разработчикам, нужно самостоятельно импортировать тестируемые методы, вызывать их с необходимыми аргументами и проверять, что методы возвращают ожидаемые значения.
Если поменялся контракт (входные данные или выход), то придётся переписывать тесты. Если контракт остался тем же, но поменялись внутренности метода, то тесты должны продолжать работать без изменений.
class StringUtils // Пример другой реализации того же самого метода public static String capitalize(String text) return Character.toUpperCase(text.charAt(0)) + text.substring(1); > >
Хорошие тесты ничего не знают про внутреннее устройство проверяемого кода. Это делает их более универсальными и надёжными.
Сколько и какие нужно писать проверки?
Невозможно написать тесты, которые гарантируют 100% работоспособность кода. Для этого потребовалось бы реализовать проверки всех возможных аргументов, что физически неосуществимо. С другой стороны, без тестов вообще нет никаких гарантий, только честное слово разработчиков.
При написании тестов нужно ориентироваться на разнообразие входных данных. У любого метода есть один или несколько основных сценариев использования. Например, в случае capitalize — это любое слово. Достаточно написать ровно одну проверку, которая покрывает этот сценарий. Дальше нужно смотреть на «пограничные случаи». Это ситуации, в которых код может повести себя по-особенному:
- Работа с пустой строкой
- Обработка null
- Деление на ноль (в большинстве языков вызывает ошибку)
- Специфические ситуации для конкретных алгоритмов
Для capitalize пограничным случаем будет пустая строка:
if (!"".equals(StringUtils.capitalize(""))) throw new AssertionError("Метод работает неверно!"); >
Добавив тест на пустую строку, мы увидим, что вызов показанного в начале урока метода capitalize завершается с ошибкой. Внутри него идёт обращение к первому индексу строки без проверки его существования. Исправленная версия кода:
public static String capitalize(String text) if ("".equals(text)) return ""; > return text.substring(0, 1).toUpperCase() + text.substring(1); >
В большом числе ситуаций пограничные случаи требуют отдельной обработки, наличия условных конструкций. Тесты должны быть построены таким образом, чтобы они затрагивали каждую такую конструкцию. Но не забывайте, что условные конструкции могут порождать хитрые связи. Например, два независимых условных блока порождают 4 возможных сценария:
- Метод выполнился так, что не был выполнен ни один условный блок
- Метод выполнился так, что был выполнен только первый условный блок
- Метод выполнился так, что был выполнен только второй условный блок
- Метод выполнился так, что были выполнены оба условных блока
Комбинация всех возможных вариантов поведения метода называется цикломатической сложностью. Это число показывает все возможные пути кода внутри метода. Цикломатическая сложность — хороший ориентир для понимания того, сколько и какие тесты нужно написать.
Иногда пограничные случаи не связаны с условными конструкциями. Особенно часто такие ситуации встречаются там, где есть вычисления границ слов или массивов. Такой код может работать в большинстве ситуаций, но только в некоторых может давать сбой:
// В этом методе забыли проверить что входной аргумент не равен null // Этот код сработает корректно в большинстве ситуаций, // Но если text == null, то программа упадёт с NullPointerException public static int len(String text) return text.length(); >
Собирая всё вместе
Содержимое класса с тестами:
package io.hexlet; public class StringUtilsTest public static void testCapitalize() if (!"Hello".equals(StringUtils.capitalize("hello"))) throw new AssertionError("Метод работает неверно!"); > if (!"".equals(StringUtils.capitalize(""))) throw new AssertionError("Метод работает неверно!"); > System.out.println("Все тесты пройдены!"); > >
Открыть доступ
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно
- 130 курсов, 2000+ часов теории
- 1000 практических заданий в браузере
- 360 000 студентов
Наши выпускники работают в компаниях:
JUnit part I


Кратко о том, зачем этот зверь нам нужен? JUnit — это фреймворк автоматического тестирования вашего хорошего или не совсем хорошего кода. Можно сказать: — зачем мне эти качели, я и так смогу легко, и просто протестировать свой хороший Java код. Можно много писать вступительной лирики, но поэт из меня никакой, перейдём лучше к делу…
Создаем объект
- Нам нужен объект, который будет хранить информацию о Пользователе.
- Id — нужно считать по порядку добавления нового пользователя.
- Имя пользователя.
- Его возраст.
- Пол (male/female)
- Формировать список всех пользователей.
- Формировать список пользователей по полу (MALE/FEMALE).
- Возвращать количество пользователей в общем списке, и посчитать количество по признаку пола пользователя.
- Посчитать общую сумму по возрасту пользователей, так же учесть по признаку пола.
- Посчитать средний возраст, как общий так и по признаку пола.
private int id; private String name; private int age; private Sex sex;Для хранения данных о пользователе этого достаточно, посмотрим что там еще нужно по задаче. Нам нужно как-то хранить всех пользователей, сделаем в нашем классе статическое поле allUsers , думаю нормально если это будет Map
private static Map allUsers;Еще нам как-то нужно присваивать порядковый номер пользователям, создадим статическое поле счетчик, который при создании нового пользователя, будет присваивать порядковый Id пользователю.
private static int countId = 0;Так, с полями вроде разобрались, напишем конструктор для нашего объекта, и гетеры для полей id , name , age , sex . C гетерами там ничего сложного нет, попросим помощи у IDEA, она никогда не откажет, а конструктор сделаем немного с хитростью. Конструктор будет уметь. Инициализировать поля, проверять есть ли такой объект в allUsers , если такого объекта нет, то увеличиваем наш счетчик countId++ , и добавляем его в список всех пользователей. А так же инициализировать поле allUsers ели оно еще не было инициализировано. Для удобства поиска одинаковых объектов, переопределим методы equals() и hashCode() , опять попросим помощи у любимой IDEA и будем сравнивать по полям name , age , sex . Плюс создадим приватный метод hasUser() , который будет проверять есть ли такой объект в списке.
@Override public boolean equals(Object o) < if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; return age == user.age && Objects.equals(name, user.name) && sex == user.sex; >@Override public int hashCode()
Конструктор в итоге у меня получился такой.
public User(String name, int age, Sex sex) < if (allUsers == null)< allUsers = new HashMap<>(); > this.name = name; this.age = age; this.sex = sex; if (!hasUser()) < countId++; this.id = countId; allUsers.put(id, this); >>и вспомогательный приватный метод
private boolean hasUser() < for (User user : allUsers.values())< if (user.equals(this) && user.hashCode() == this.hashCode())< return true; >> return false; >а также переопределим toString()
public static int getHowManyUsers() < return allUsers.size(); >public static int getHowManyUsers(Sex sex)
public static int getAllAgeUsers() < int countAge = 0; for (User user : allUsers.values())< countAge += user.age; >return countAge; > public static int getAllAgeUsers(Sex sex) < int countAge = 0; for (User user : getAllUsers(sex))< countAge += user.age; >return countAge; >public static int getAverageAgeOfAllUsers() < return getAllAgeUsers() / getHowManyUsers(); >public static int getAverageAgeOfAllUsers(Sex sex) < return getAllAgeUsers(sex) / getHowManyUsers(sex); >Отлично, требуемый объект и его поведение мы описали. Теперь можно переходить к JUnit, но для начала покажу как примерно будет выглядеть простой тест если мы его будет делать в main.
public static void main(String[] args) < new User("Евгений", 35, Sex.MALE); new User("Марина", 34, Sex.FEMALE); new User("Алина", 7, Sex.FEMALE); System.out.println("Все пользователи:"); User.getAllUsers().forEach(System.out::println); System.out.println("Все пользователи: MALE"); User.getAllUsers(Sex.MALE).forEach(System.out::println); System.out.println("Все пользователи: FEMALE"); User.getAllUsers(Sex.FEMALE).forEach(System.out::println); System.out.println("================================================"); System.out.println(" всех пользователей: " + User.getHowManyUsers()); System.out.println(" всех пользователей MALE: " + User.getHowManyUsers(Sex.MALE)); System.out.println("всех пользователей FEMALE: " + User.getHowManyUsers(Sex.FEMALE)); System.out.println("================================================"); System.out.println(" общий возраст всех пользователей: " + User.getAllAgeUsers()); System.out.println(" общий возраст всех пользователей MALE: " + User.getAllAgeUsers(Sex.MALE)); System.out.println("общий возраст всех пользователей FEMALE: " + User.getAllAgeUsers(Sex.FEMALE)); System.out.println("================================================"); System.out.println(" средний возраст всех пользователей: " + User.getAverageAgeOfAllUsers()); System.out.println(" средний возраст всех пользователей MALE: " + User.getAverageAgeOfAllUsers(Sex.MALE)); System.out.println("средний возраст всех пользователей FEMALE: " + User.getAverageAgeOfAllUsers(Sex.FEMALE)); System.out.println("=============================================== lang-java line-numbers">//output Все пользователи: User User User Все пользователи: MALE User Все пользователи: FEMALE User User ================================================ всех пользователей: 3 всех пользователей MALE: 1 всех пользователей FEMALE: 2 ================================================ общий возраст всех пользователей: 76 общий возраст всех пользователей MALE: 35 общий возраст всех пользователей FEMALE: 41 ================================================ средний возраст всех пользователей: 25 средний возраст всех пользователей MALE: 35 средний возраст всех пользователей FEMALE: 20 ================================================ Process finished with exit code 0Как подключить JUnit к проекту
Возникает вопрос, как его подключить к проекту. Для знающих вариант с Mavenбрать не буду, так как это совсем другая история. 😉 Открываем структуру проекта Ctrl + Alt + Shift + S -> Libraries -> жмем + (New Project Library) -> выбираем from Maven
дальше видим такое окно, в строку поиска вводим “ junit:junit:4.12 ” ждем пока найдет -> OK! -> OK!
Должен получиться такой результат
Жмем OK, поздравлю JUnit добавлен к проекту. Едем дальше. Теперь нам нужно создать тесты для нашего Java класса, ставим курсор на название класса User -> жмем Alt + Enter -> выбираем create Test. Мы должны увидеть окно, в котором нам нужно выбрать библиотеку JUnit4 -> выбрать методы которые собираемся тестировать -> OK
Идея сама создаст класс UserTest , это и есть класс, в котором мы будем покрывать наш код тестами. Приступим:Наш первый @Test
Создадим наш первый @Test метода getAllUsers() – это метод который должен вернуть всех пользователей. Тест будет выглядеть примерно так:
@Test public void getAllUsers() < //создаем тестовые данные User user = new User("Евгений", 35, Sex.MALE); User user1 = new User("Марина", 34, Sex.FEMALE); User user2 = new User("Алина", 7, Sex.FEMALE); //создаем список expected и заполняем его данными нашего метода Listexpected = User.getAllUsers(); //создаем список actual в него помещаем данные для сравнения //то что мы предпологиаем метод должен вернуть List actual = new ArrayList<>(); actual.add(user); actual.add(user1); actual.add(user2); //запускаем тест, в случае если список expected и actual не будут равны //тест будет провален, о результатах теста читаем в консоли Assert.assertEquals(expected, actual); >
Тут мы создаем несколько тестовых пользователей -> создаем список expected в который поместим пользователей которых нам вернет метод getAllUsers() -> создадим список actual в который поместим пользователей которых мы предполагаем что метод getAllUsers() Assert.assertEquals(actual, expected) ему мы и передадим списки, инспектируемый и актуальный. Этот метод проверит объекты в предоставленных списках и выдаст результат теста. Метод будет сравнивать все поля объектов, даже пройдется по полям родителей, если есть наследование. Запускаем первый тест. Тест выполнен успешно. Теперь попробуем сделать так, чтобы тест был провален, для этого нам нужно изменить один из списков теста, сделаем это путем, закомментировав добавление одного пользователя в список actual ,
@Test public void getAllUsers() < //создаем тестовые данные User user = new User("Евгений", 35, Sex.MALE); User user1 = new User("Марина", 34, Sex.FEMALE); User user2 = new User("Алина", 7, Sex.FEMALE); //создаем список expected и заполняем его данными нашего метода Listexpected = User.getAllUsers(); //создаем список actual в него помещаем данные для сравнения //то что мы предпологиаем метод должен вернуть List actual = new ArrayList<>(); actual.add(user); actual.add(user1); //actual.add(user2); //запускаем тест, в случае если список expected и actual не будут равны //тест будет провален, о результатах теста читаем в консоли Assert.assertEquals(expected, actual); >
запускаем тест и видим следующее: Теперь мы можем немного разобрать причину провала теста. Тут мы видим, что в инспектируемом списке больше пользователей чем в актуальном. Это и есть причина провала. А в main мы можем проверить так? JUnit : main = 1 : 0. Давайте посмотрим как будет выглядеть тест, если в нем будут полностью разные объекты, сделаем это так:
@Test public void getAllUsers() < //создаем тестовые данные User user = new User("Евгений", 35, Sex.MALE); User user1 = new User("Марина", 34, Sex.FEMALE); User user2 = new User("Алина", 7, Sex.FEMALE); //создаем список expected и заполняем его данными нашего метода Listexpected = User.getAllUsers(); //создаем список actual в него помещаем данные для сравнения //то что мы предпологиаем метод должен вернуть List actual = new ArrayList<>(); actual.add(new User("User1", 1, Sex.MALE)); actual.add(new User("User2", 2, Sex.FEMALE)); actual.add(new User("User3", 3, Sex.MALE)); //запускаем тест, в случае если список expected и actual не будут равны //тест будет провален, о результатах теста читаем в консоли Assert.assertEquals(expected, actual); >
вот что будет в консоли: тут сразу видно что в сравниваемых списках разные пользователи, еще мы можем кликнуть на <Click to see difference> получим такое окно, где можно посмотреть подробно с какими данными у нас проблема. IDEA подсветит все поля в которых есть различия. main такое может? — нет. JUnit : main = 2 : 0 Ну что, пойдем дальше у нас еще куча методов, которые нужно покрыть тестами ), но подождите, а ведь будет не плохо, проверить, а не будет ли нам метод getAllUsers() возвращать null , ведь примерно так нас на задачах JavaRush ловит валидатор ). Сделаем это, делов то на три копейки …
@Test public void getAllUsers_NO_NULL() < //добавим проверку на null Listexpected = User.getAllUsers(); Assert.assertNotNull(expected); >
Да, да примерно так валидатор ловит наш
говнокод на null 😉 Теперь запустим этот тест, и посмотрим, что он нам покажет. А покажет он ошибку, как . как же тут можно было допустить ошибку теста))) И тут мы можем пожинать первые плоды покрытия своего кода тестами. Как вы помните, поле allUsers мы инициализировали в конструкторе, и значит при вызове метода getAllUsers() , мы обратимся к объекту, который еще не был инициализирован. Будем править, уберем инициализацию из конструктора, и сделаем ее при объявлении поля.private static Map allUsers = new HashMap<>(); public User(String name, int age, Sex sex) < this.name = name; this.age = age; this.sex = sex; if (!hasUser()) < countId++; this.id = countId; allUsers.put(id, this); >>
Запустим тест, теперь все хорошо. не думаю что в main легко будет отловить NPE, думаю вы согласитесь что счет JUnit : main = 3 : 0 Дальше я все методы покрою тестами, и дам вам посмотреть, как это будет выглядеть. Теперь класс тестов у нас выглядит так:
package user; import org.junit.Assert; import org.junit.Test; import java.util.ArrayList; import java.util.List; import static org.junit.Assert.*; public class UserTest < @Test public void getAllUsers() < //создаем тестовые данные User user = new User("Евгений", 35, Sex.MALE); User user1 = new User("Марина", 34, Sex.FEMALE); User user2 = new User("Алина", 7, Sex.FEMALE); //создаем список expected и заполняем его данными нашего метода Listexpected = User.getAllUsers(); //создаем список actual в него помещаем данные для сравнения //то что мы предпологиаем метод должен вернуть List actual = new ArrayList<>(); actual.add(user); actual.add(user1); actual.add(user2); //запускаем тест, в случае если список expected и actual не будут равны //тест будет провален, о результатах теста читаем в консоли Assert.assertEquals(expected, actual); > @Test public void getAllUsers_NO_NULL() < //добавим проверку на null Listexpected = User.getAllUsers(); Assert.assertNotNull(expected); > @Test public void getAllUsers_MALE() < User user = new User("Евгений", 35, Sex.MALE); User user1 = new User("Марина", 34, Sex.FEMALE); User user2 = new User("Алина", 7, Sex.FEMALE); Listexpected = User.getAllUsers(Sex.MALE); List actual = new ArrayList<>(); actual.add(user); Assert.assertEquals(expected, actual); > @Test public void getAllUsers_MALE_NO_NULL() < //добавим проверку на null Listexpected = User.getAllUsers(Sex.MALE); Assert.assertNotNull(expected); > @Test public void getAllUsers_FEMALE() < User user = new User("Евгений", 35, Sex.MALE); User user1 = new User("Марина", 34, Sex.FEMALE); User user2 = new User("Алина", 7, Sex.FEMALE); Listexpected = User.getAllUsers(Sex.FEMALE); List actual = new ArrayList<>(); actual.add(user1); actual.add(user2); Assert.assertEquals(expected, actual); > @Test public void getAllUsers_FEMALE_NO_NULL() < //добавим проверку на null Listexpected = User.getAllUsers(Sex.FEMALE); Assert.assertNotNull(expected); > @Test public void getHowManyUsers() < User user = new User("Евгений", 35, Sex.MALE); User user1 = new User("Марина", 34, Sex.FEMALE); User user2 = new User("Алина", 7, Sex.FEMALE); int expected = User.getHowManyUsers(); int actual = 3; Assert.assertEquals(expected, actual); >@Test public void getHowManyUsers_MALE() < User user = new User("Евгений", 35, Sex.MALE); User user1 = new User("Марина", 34, Sex.FEMALE); User user2 = new User("Алина", 7, Sex.FEMALE); int expected = User.getHowManyUsers(Sex.MALE); int actual = 1; Assert.assertEquals(expected, actual); >@Test public void getHowManyUsers_FEMALE() < User user = new User("Евгений", 35, Sex.MALE); User user1 = new User("Марина", 34, Sex.FEMALE); User user2 = new User("Алина", 7, Sex.FEMALE); int expected = User.getHowManyUsers(Sex.FEMALE); int actual = 2; Assert.assertEquals(expected, actual); >@Test public void getAllAgeUsers() < User user = new User("Евгений", 35, Sex.MALE); User user1 = new User("Марина", 34, Sex.FEMALE); User user2 = new User("Алина", 7, Sex.FEMALE); int expected = User.getAllAgeUsers(); int actual = 35 + 34 + 7; Assert.assertEquals(expected, actual); >@Test public void getAllAgeUsers_MALE() < User user = new User("Евгений", 35, Sex.MALE); User user1 = new User("Марина", 34, Sex.FEMALE); User user2 = new User("Алина", 7, Sex.FEMALE); int expected = User.getAllAgeUsers(Sex.MALE); int actual = 35; Assert.assertEquals(expected, actual); >@Test public void getAllAgeUsers_FEMALE() < User user = new User("Евгений", 35, Sex.MALE); User user1 = new User("Марина", 34, Sex.FEMALE); User user2 = new User("Алина", 7, Sex.FEMALE); int expected = User.getAllAgeUsers(Sex.FEMALE); int actual = 34 + 7; Assert.assertEquals(expected, actual); >>Да не маленький получился, а что же будет при работе с большими проектами. Что же тут можно сократить, оценив все можно заметить, что тестовые данные мы создаем в каждом тесте, и тут нам на помощь приходят аннотации. Возьмем @Before — Аннотация @Before указывает на то, что метод будет выполнятся перед каждым тестируемым методом @Test . Вот так теперь будет выглядеть наш класс тестов с аннотацией @Before :
package user; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import java.util.ArrayList; import java.util.List; import static org.junit.Assert.*; public class UserTest < private User user; private User user1; private User user2; @Before public void setUp() throws Exception < user = new User("Евгений", 35, Sex.MALE); user1 = new User("Марина", 34, Sex.FEMALE); user2 = new User("Алина", 7, Sex.FEMALE); >@Test public void getAllUsers() < Listexpected = User.getAllUsers(); List actual = new ArrayList<>(); actual.add(user); actual.add(user1); actual.add(user2); Assert.assertEquals(expected, actual); > @Test public void getAllUsers_NO_NULL() < Listexpected = User.getAllUsers(); Assert.assertNotNull(expected); > @Test public void getAllUsers_MALE() < Listexpected = User.getAllUsers(Sex.MALE); List actual = new ArrayList<>(); actual.add(user); Assert.assertEquals(expected, actual); > @Test public void getAllUsers_MALE_NO_NULL() < //добавим проверку на null Listexpected = User.getAllUsers(Sex.MALE); Assert.assertNotNull(expected); > @Test public void getAllUsers_FEMALE() < Listexpected = User.getAllUsers(Sex.FEMALE); List actual = new ArrayList<>(); actual.add(user1); actual.add(user2); Assert.assertEquals(expected, actual); > @Test public void getAllUsers_FEMALE_NO_NULL() < //добавим проверку на null Listexpected = User.getAllUsers(Sex.FEMALE); Assert.assertNotNull(expected); > @Test public void getHowManyUsers() < int expected = User.getHowManyUsers(); int actual = 3; Assert.assertEquals(expected, actual); >@Test public void getHowManyUsers_MALE() < int expected = User.getHowManyUsers(Sex.MALE); int actual = 1; Assert.assertEquals(expected, actual); >@Test public void getHowManyUsers_FEMALE() < int expected = User.getHowManyUsers(Sex.FEMALE); int actual = 2; Assert.assertEquals(expected, actual); >@Test public void getAllAgeUsers() < int expected = User.getAllAgeUsers(); int actual = 35 + 34 + 7; Assert.assertEquals(expected, actual); >@Test public void getAllAgeUsers_MALE() < int expected = User.getAllAgeUsers(Sex.MALE); int actual = 35; Assert.assertEquals(expected, actual); >@Test public void getAllAgeUsers_FEMALE() < int expected = User.getAllAgeUsers(Sex.FEMALE); int actual = 34 + 7; Assert.assertEquals(expected, actual); >>Ну как вам, уже веселее и легче читать 😉 Вот список аннотаций для JUnit с ними однозначно жить проще.
@Test – определяет что метод method() является тестовым. @Before – указывает на то, что метод будет выполнятся перед каждым тестируемым методом @Test. @After – указывает на то что метод будет выполнятся после каждого тестируемого метода @Test @BeforeClass – указывает на то, что метод будет выполнятся в начале всех тестов, а точней в момент запуска тестов(перед всеми тестами @Test). @AfterClass – указывает на то, что метод будет выполнятся после всех тестов. @Ignore – говорит, что метод будет проигнорирован в момент проведения тестирования. (expected = Exception.class) – указывает на то, что в данном тестовом методе вы преднамеренно ожидаете Exception. (timeout = 100) – указывает, что тестируемый метод не должен занимать больше чем 100 миллисекунд.Основные методы класса Assert для проверки:
fail(String) – указывает на то что бы тестовый метод завалился при этом выводя текстовое сообщение. assertTrue([message], boolean condition) – проверяет, что логическое условие истинно. assertsEquals([String message], expected, actual) – проверяет, что два значения совпадают. Примечание: для массивов проверяются ссылки, а не содержание массивов. assertNull([message], object) – проверяет, что объект является пустым null. assertNotNull([message], object) – проверяет, что объект не является пустым null. assertSame([String], expected, actual) – проверяет, что обе переменные относятся к одному объекту. assertNotSame([String], expected, actual) – проверяет, что обе переменные относятся к разным объектам.Вот так мы можем добавить зависимость JUnit 4.12 в Maven
junit junit 4.12 test