1. Введение
Тестирование – это процесс проверки функционала программы с целью подтверждения того, что она работает в соответствии с определёнными требованиями. Unit-тестирование – это тестирование с помощью тестов, которые пишутся, непосредственно, на уровне разработчика (тестирование определённой сущности – метод или класс). Это крайне важный этап разработки ПО, который помогает создавать качественный продукт.
Unit-тестирование делится на две большие группы:
-
Ручное тестирование
-
Автоматизированное тестирование
Ручное тестирование | Автоматизированное тестирование |
---|---|
Ручное выполнение тестов без помощи каких-либо средств. |
Использование специальных средств для автоматизированного тестирования |
Не программируется |
Программируется |
Низкая надёжность |
Высокая надёжность |
Большие затраты времени |
Быстро |
2. JUnit
JUnit – это фреймворк, разработанный для тестирования программ, написанных с использованием технологии Java. Он лежит в основе TDD (Test-Driven Development) и входит в семейство фреймворков для тестирования xUnit.
Главная идея Test-Driven Development – сначала тесты, потом код. Это означает, что сначала определяется, что должно получиться в результате работы того или иного куска кода и пишем тесты. Тесты проверяют идентичность результата с требуемым, после чего пишем сам кусок кода, который и будет тестироваться. Данный подход увеличивает эффективность работы разработчика и позволяет писать более стабильный код. В результате этого получается меньшее количество времени, которое затрачивается на отладку программы.
2.1. Свойства JUnit
-
Фреймворк с открытым исходным кодом, который используется для написания и выполнения тестов.
-
Позволяет писать код более быстро и качественно.
-
Крайне прост в использовании.
-
Поддерживает аннотации для идентификации методов.
-
Поддерживает утверждения для тестирования получаемых результатов.
-
Тесты могут быть организованы в test suites (связки тестов).
-
Имеет визуальную индикацию состояния тестов (красные – не пройдены, зелёные – пройдены).
3. Тестовый случай
Test Case (Тестовый случай) в unit-тестировании – это часть кода, которая проверяет, что другая часть кода, например метод, работает в соответствии с определёнными требованиями.
Формально описанный test case характеризуется известными входными данными и ожидаемым выводом программы, который известен до начала выполнения теста.
Необходимо создавать, как минимум, два test cases для каждого требования – положительный и отрицательный. Если требование имеет под-требования, каждое из них должно тестироваться отдельно.
4. JUnit 5
JUnit 5 требует Java 8 (или выше) для запуска. Однако все равно можно протестировать код, скомпилированный с предыдущими версиями JDK.
В отличие от предыдущих версий JUnit, JUnit 5 состоит из нескольких разных модулей из трех разных подпроектов.
JUnit 5 = Platform JUnit + JUnit Jupiter + JUnit Vintage
-
Platform JUnit
Служит основой для запуска тестирования на JVM. Он также определяет Test Engine API для разработки инфраструктуры тестирования, работающей на платформе. Кроме того, платформа предоставляет инструменты для запуска тестов с помощью CLI и инструменты для запуска на основе JUnit 4 для запуска любого Test Engine. Первоклассная поддержка Platform JUnit также существует в популярных IDE (см. IntelliJ IDEA, Eclipse, NetBeans и Visual Studio Code) и инструментах сборки (см. Gradle, Maven и Ant). -
JUnit Jupiter
Является сочетанием новой модели программирования и модели расширения для написания тестов и расширений в JUnit 5. JUnit Jupiter обеспечивает Test Engine для выполнения тестов на основе Jupiter на Platform JUnit. -
JUnit Vintage
Обеспечивает Test Engine запуск тестов на основе JUnit 3 и JUnit 4 на Platform JUnit.
4.1. Аннотации
JUnit Jupiter поддерживает следующие аннотации для настройки тестов и расширения фреймворка.
Аннотация | Свойство |
---|---|
|
Означает, что метод является методом тестирования. В отличие от аннотации JUnit 4, эта аннотация не объявляет никаких атрибутов, так как тестовые расширения в JUnit Jupiter работают на основе собственных специальных аннотаций. Такие методы наследуются, если они не переопределены. |
|
Означает, что метод является параметризованным тестом. Такие методы наследуются, если они не переопределены. |
|
Означает, что метод является тестовым шаблоном для повторного теста. Такие методы наследуются, если они не переопределены. |
|
Означает, что метод является испытательным заводом для динамических тестов. Такие методы наследуются, если они не переопределены. |
|
Означает, что метод является шаблоном для тестовых случаев, предназначенных для вызова несколько раз в зависимости от количества контекстов вызова, возвращенных зарегистрированными поставщиками. Такие методы наследуются, если они не переопределены. |
|
Используется для настройки порядка выполнения тестового метода для аннотированного тестового класса; похож на JUnit 4’s. Такие аннотации наследуются. |
|
Используется для настройки жизненного цикла экземпляра теста для аннотированного тестового класса. Такие аннотации наследуются. |
|
Объявляет пользовательское имя дисплея для тестового класса или метода тестирования. Такие аннотации не наследуются. |
|
Объявляет пользовательский генератор имен отображения для тестового класса. Такие аннотации наследуются. |
|
Означает, что аннотированный метод должен быть выполнен перед каждым, или методом в текущем классе; по аналогии с JUnit 4’s. Такие методы наследуются, если они не переопределены. |
|
Означает, что аннотированный метод должен быть выполнен после каждого, или метода в текущем классе; по аналогии с JUnit 4’s. Такие методы наследуются, если они не переопределены. |
|
Означает, что аннотированный метод должен быть выполнен прежде всего, и методы в текущем классе; по аналогии с JUnit 4’s. Такие методы наследуются (если они не скрыты или переопределены)и должны быть (если не используется жизненный цикл "в каждом классе" экземпляра теста). |
|
Означает, что аннотированный метод должен быть выполнен в конце концов, и методы в текущем классе; по аналогии с JUnit 4’s. Такие методы наследуются (если они не скрыты или переопределены)и должны быть (если не используется жизненный цикл "в каждом классе" экземпляра теста). |
|
Означает, что аннотированный класс является не статичным вложенным тестовым классом и методы не могут быть использованы непосредственно в тестовом классе, если не используется жизненный цикл экземпляра теста "на класс". Такие аннотации не наследуются. |
|
Используется для объявления тегов для фильтрации тестов, либо на уровне класса или метода; аналогично тестовым группам в TestNG или Categories в JUnit 4. Такие аннотации наследуются на уровне класса, но не на уровне метода. |
|
Используется для отключения тестового класса или метода тестирования; по аналогии с JUnit 4’s. Такие аннотации не наследуются.@Ignore |
|
Используется для неудачи теста, испытательного завода, шаблона тестирования или метода жизненного цикла, если его выполнение превышает данный срок. Такие аннотации наследуются. |
|
Используется для регистрации расширений декларативно. Такие аннотации наследуются. |
|
Используется для регистрации расширений программно через поля. Такие поля наследуются, если они не затенены. |
|
Используется для поставки временного каталога с помощью инъекций поля или инъекций параметра в метод жизненного цикла или метод тестирования; расположен в пакете |
Все основные аннотации находятся в org.junit.jupiter.api пакете в junit-jupiter-api модуле.
4.2. Assertions
JUnit 5 поставляется со многими стандартными Assertions (утверждениями), т.е. методами, которые проверяют результат работы кода на соответствие ожидаемому результату. Их можно найти в классе org.junit.jupiter.api.Assertions
Основные assertions:
-
assertEquals()
, -
assertArrayEquals()
, -
assertSame()
, -
assertNotSame()
, -
assertTrue()
, -
assertFalse()
, -
assertNull()
, -
assertNotNull()
, -
assertLinesMatch()
, -
assertIterablesMatch()