1. Главная страница » Компьютеры

Junit тесты для чайников java

Автор: | 16.12.2019

English version of this article you can find here.

Тестирование далеко не всегда бывает веселым и интересным. Этот процесс обычно достаточно продолжителен и порой полон монотонной работы. Кажется, еще совсем недавно программисты пользовались стандартным выводом или же дебаггером для тестирования java классов.

В этой статье я опишу библиотеку JUnit 4, которая во многом упрощает и автоматизирует процесс написания тестов.

Для демонстрации основных возможностей JUnit Framework, напишем примитивный класс на языке Java и будем над ним издеваться. Этот класс будет иметь два метода — нахождение факториала неотрицательного числа и суммы двух чисел. Кроме того, в экземпляре класса будет находится счетчик вызовов методов.

Теперь напишем Unit тесты. Для этого создадим класс с некоторым количеством тестовых методов. Естественно, класс может содержать и обычные вспомогательные методы. Чтобы runner тестов мог определить, кто есть кто, тестовые методы необходимо помечать аннтоацией @Test.

У аннотации могут быть проставлены такие параметры:

  • expected — указываем какое исключение будет сгенерировано методом (см. пример ниже);
  • timeout — через какое время в милисекундах прекратить выполнение теста и засчитать его как неуспешный.

Если вы хотите указать, что определенный тест необхдимо пропустить, то пометьте его аннотацией @Ignore. Хотя можно просто удалить аннотацию @Test.

Бывает такое, что для выполнения каждого тестового сценария вам необходим некоторый контекст, например, заранее созданные экземпляры классов. А после выполнения нужно освободить зарезервированные ресурсы. В этом случае вам понадобятся аннтоации @Before и @After. Метод, помеченный @Before будет выполняться перед каждым тестовым случаем, а метод, помеченный @After — после каждого тестового случая.

Если же инициализацию и освобождение ресурсов нужно сделать всего один раз — соответственно до и после всех тестов — то используйте пару аннотаций @BeforeClass и @AfterClass.

А вот и сам тестовый класс с несколькими тестовыми сценариями:

Метод calls тестирует правильность счетчика вызовов. Метод factorial проверяет правильность вычисления факториала для некоторых стандартных значений. Метод factorialNegative проверяет, что для отрицательных значений факотриала будет брошен IllegalArgumentException. Метод todo будет проигнорирован. Попробуйте убрать аннотацию @Ignore, когда будете экспериментировать с кодом.

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

  • assertEquals — ожидаемый результат и полученный результат совпадают;
  • assertNull — результатом выражения есть null;
  • assertNotNull — результат выражения отличен от null;
  • assertSame — ожидаемый и полученный объекты это один и тот же объект.
  • fail — метод генерирует исключение AssertionError — добавляем туда, куда не должен дойти ход выполнения программы.

В нашем современном мире IDE умеют находить и просто запускать тесты в проекте. Но что делать, если вы хотите запустить их вручную с помощью программного кода. Для этого можно воспользоваться Runner’ом. Бывают текстовый — junit.textui.TestRunner, графические версии — junit.swingui.TestRunner, junit.awtui.TestRunner.

Но чуть более современный метод — это использование класса JUnitCore. Добавьте следующий метод main в класс MathFuncTest:

И результат выполнения:

В более ранних версиях JUnit для написания тестового класса нужно было создать наследника junit.framework.TestCase. Затем необходимо было определить конструктор, принимающий в качестве параметра String — название метода — и передать его родительскому классу. Каждый тестовый метод обязан был начинаться с префикса test. Для инициализации и освобождения ресурсов использовались методы setUp и tearDown. Короче ужас. Ну а сейчас все просто, да.

Вот и все на сегодня. Уверен, JUnit Framework во многом поможет вам. Комментарии и вопросы по поводу статьи приветствуются.

JUnit — библиотека для модульного тестирования программ Java. Созданный Кентом Беком и Эриком Гаммой, JUnit принадлежит семье фреймворков xUnit для разных языков программирования, берущей начало в SUnit Кента Бека для Smalltalk. JUnit породил экосистему расширений — JMock, EasyMock, DbUnit, HttpUnit и т. д.

Библиотека JUnit была портирована на другие языки, включая PHP (PHPUnit), C# (NUnit), Python (PyUnit), Fortran (fUnit), Delphi (DUnit), Free Pascal (FPCUnit), Perl (Test::Unit), C++ (CPPUnit), Flex (FlexUnit), JavaScript (JSUnit).

JUnit – это Java фреймворк для тестирования, т. е. тестирования отдельных участков кода, например, методов или классов. Опыт, полученный при работе с JUnit, важен в разработке концепций тестирования программного обеспечения.

Пример теста JUnit

Необходимость использования JUnit

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

Юнит тесты классов и функций являются своего рода документацией к тому, что ожидается в результате их выполнения. И не просто документацией, а документацией которая может автоматически проверять код на соответствие предъявленным функциям. Это удобно, и часто тесты разрабатывают как вместе, так и до реализации классов. Разработка через тестирование — крайне популярная технология создания серьезного программного обеспечения.

Виды тестирования и место JUnit тестирования в классификации

Тестирование программного обеспечение можно разделить на два вида:

  • тестирование черного ящика;
  • тестирование белого ящика.

Во время тестирования программы как черного ящика внутренняя структура приложения в расчет не принимается. Все, что имеет значение, это функциональность, которую приложение должно обеспечить. При тестировании программы как белого ящика во внимание принимается внутренняя структура, т.е. класс и методы. Кроме этого, тестирование можно разделить на четыре уровня:

  • юнит тесты — тестирование отдельных участков кода;
  • интеграционное тестирование — тестирование взаимодействия и совместной работы компонентов;
  • системное тестирование — тестирование всей системы как целого;
  • приемное тестирование — итоговое тестирование готовой системы на соответствие требованиям.

Юнит тестирование по определению является тестированием белого ящика.

Используется unit тестирование в двух вариантах — JUnit 3 и JUnit 4. Рассмотрим обе версии, так как в старых проектах до сих пор используется 3-я версия, которая поддерживает Java 1.4.

JUnit 3

Для создания теста следует наследовать тест-класс TestCase, переопределить методы setUp и tearDown при необходимости, ну и самое главное — разработать тестовые методы, наименование которых должно начинаться с аббривиатуры "test". При запуске теста сначала создается экземляр тест-класса (для каждого теста в классе отдельный экземпляр класса), затем выполняется метод setUp, запускается сам тест, ну и в завершение выполняется метод tearDown. Если какой-либо из методов вызывает исключение, тест считается провалившимся.

Примечание : тестовые методы должны быть public void, могут быть static.

Тесты состоят из выполнения некоторого кода и проверок. Проверки чаще всего выполняются с помощью класса Assert хотя иногда используют ключевое слово assert.

В качестве примера рассмотрим утилиту для работы со строками, включающую методы для проверки пустой строки и представления последовательности байт в виде 16-ричной строки:

Дополнительные возможности, TestSuite

JUnit 3 имеет несколько дополнительных возможностей. Например, можно группировать тесты. Для этого необходимо использовать класс TestSuite:

Можно исполнение теста повторить несколько раз. Для этого используется RepeatedTest :

Наследуя тест-класс от ExceptionTestCase, можно проверить код на выброс исключения :

Как видно из примеров все довольно просто и ничего лишнего — минимум кода для JUnit тестирования.

JUnit 4

В JUnit 4 добавлена поддержка новых возможностей из Java 5.0; тесты могут быть объявлены с помощью аннотаций. При этом существует обратная совместимость с предыдущей версией фреймворка. Практически все рассмотренные выше примеры будут работать и в JUnit 4 за исключением RepeatedTest, который отсутствует в новой версии.

Какие внесены изменения появились в JUnit 4? Рассмотрим тот же пример, но уже с использованием новых возможностей :

Что изменилось в JUnit 4 ?

  • Для упрощения работы можно наследоваться от класса Assert, хотя это необязательно.
  • Аннотация @Before обозначает методы, которые будут вызваны перед исполнением тестов. Методы должны быть public vo >

Игнорирование выполнения теста, JUnit Ignore

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

Правила тастирования, JUnit Rule

JUnit позволяет использовать определенные разработчиком правила до и после выполнения теста, которые расширяют функционал. Например, есть встроенные правила для задания таймаута для теста (Timeout), для задания ожидаемых исключений (ExpectedException), для работы с временными файлами(TemporaryFolder) и др.

Для объявления правила необходимо создать public не static поле типа производного от MethodRule и аннотировать его с помощью ключевого слова Rule.

Наборы тестов, JUnit Suite, SuiteClasses

Запуск теста может быть сконфигурирован с помощью аннотации @RunWith. Тестовые классы, которые содержат в себе тестовые методы, можно объединить в наборы тестов (Suite). Например, создано два класса тестирования объектов : TestFilter, TestConnect. Эти два тестовых класса можно объединить в один тестовый класс TestWidgets.java :

Для настройки запускаемых тестов используется аннотация @SuiteClasses, в которую включены тестовые классы.

Аннотация Categories

Аннотация Categories позволяет объединить тесты в категории (группы). Для этого в тесте определяется категория @Category, после чего настраиваются запускаемые категории тестов в Suite. Это может выглядеть следующим образом:

Аннотация, JUnit Parameterized

Аннотация Parameterized позволяет использовать параметризированные тесты. Для этого в тест-классе объявляется статический метод, возвращающий список данных, которые будут использованы в качестве аргументов конструктора класса.

Параметризирование метода : Theories.class, DataPoints, DataPoint, Theory

Аннотация Theories параметризирует тестовый метод, а не конструктор. Данные помечаются с помощью @DataPoints и @DataPoint, тестовый метод — с помощью @Theory. Тест, использующий этот функционал, может выглядеть примерно следующим образом :

Порядок выполнения тестов

Если необходимо выполнить тест в определенном порядке, то можно воспользоваться аннотацией @FixMethodOrder(MethodSorters.NAME_ASCENDING), определенной в JUnit 4.11. Например :

В противном случае можно использовать следующие 2 подхода.

Список основных аннотаций

Аннотация Описание
@Test
public void testMethod()
метод является тестовым
@Test(timeout=100)
public void testMethod()
если время выполнения превысит параметр timeout, то тест будет завершен неудачно
@Test (expected = MyException.class)
public void testMethod()
метод должен выбросить исключение принадлежащие к классу MyException, в противном случае тест будет завершен неудачно
@Ignore
public void testMethod()
игнорировать тестовый метод
@BeforeClass
public static void testMethod()
метод вызывающийся один раз для класса перед выполнением тестовых методов; здесь можно разместить инициализацию которую нужно выполнять только один раз, например, прочитать данные, которые будут использоваться в тестовых методах или создать соединение с базой данных
@AfterClass
public static void testMethod()
метод вызывающийся один раз для класса после выполнения тестовых методов; здесь можно разместить деинициализацию которую нужно выполнять только один раз, например, закрыть соединение с базой данных или удалить данные, которые больше не нужны
@Before
public static void beforeMethod()
метод, вызывающийся перед каждым тестовым методом в тестовом классе; здесь можно выполнить необходимую инициализацию, например, выставить начальные параметры
@After
public static void afterMethod()
метод, вызывающийся после каждого тестового метода в тестовом классе; здесь можно выполнить необходимую деинициализацию, например, удалить данные, которые больше не нужны

Список типов проверок Asserts

Тип проверки Описание
fail()
fail(String message)
прерывание теста с ошибкой, т.е. тест будет неудачным
assertTrue(boolean condition)
assertTrue(java.lang.String message, boolean condition)
проверка на равенство условия condition значению true
assertFalse(boolean condition)
assertFalse(String message, boolean condition)
проверка на равенство условия condition значению false
assertEquals( expected, actual)
assertEquals(String message, expected, actual)
проверка на равенство; — это Object, int, double и т.д.
assertArrayEquals(byte[] expecteds, byte[] actuals)
assertArrayEquals(String message, [] expecteds, [] actuals)
проверка массивов на равенство; аналогично assertEquals; — это Object, int, double и т.д.
assertNotNull(Object object)
assertNotNull(String message, Object object)
проверка, что Object не null
assertNull(Object object)
assertNull(String message, Object object)
проверка, что Object null
assertSame(Object expected, Object actual)
assertSame(String message, Object expected, Object actual)
проверка на равенство двух объектов expected и actual, т.е. один и тот же объект

Пример JUnit тестирования

Для демонстрации основных возможностей JUnit, используем примитивный java класс FuncMath, который имеет два метода — нахождение факториала неотрицательного числа и суммы двух чисел. Кроме того, в экземпляре класса будет находится счетчик вызовов методов.

Иногда для выполнения каждого тестового сценария необходим некоторый контекст, например, заранее созданные экземпляры классов. А после выполнения нужно освободить зарезервированные ресурсы. В этом случае используют аннтоации @Before и @After. Метод, помеченный @Before будет выполняться перед каждым тестовым случаем, а метод, помеченный @After — после каждого тестового случая. Если же инициализацию и освобождение ресурсов нужно сделать всего один раз — соответственно до и после всех тестов — то используют пару аннотаций @BeforeClass и @AfterClass.

Тестовый класс с несколькими сценариями будет иметь следующий вид :

Метод calls тестирует правильность счетчика вызовов. Метод factorial проверяет правильность вычисления факториала для некоторых стандартных значений. Метод factorialNegative проверяет, что для отрицательных значений факотриала будет брошен IllegalArgumentException. Метод todo будет проигнорирован.

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

Java в примерах для начинающих

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

Создадим пустой maven проект:

И добавим в него JUnit:

Зависимость добавлена с test , что говорит maven, что она требуется только при сборке и исполнении тестов.

Поскольку я обещал почти настоящий пример, придётся написать хоть сколько-то полезный класс. Пускай это будем набор утилит для работы со строками:

  • Разделение строки на подстроки
  • Слияние строк из массива
  • Проверка строк на пустоту
  • Преобразование в число и обратно

Тесты в JUnit располагаются в отдельных классах, методы которых, имеющие аннотацию @Test , и возвращающие void , и есть сами тесты. Имя класса может быть в принципе любое, но рекомендуется придерживаться шаблона ИмяТестируемогоКласса Test , так как это упрощает чтение кода. К тому же обычно средства автоматического запуска тестов, такие как плагин maven maven — surefire — plugin предполагают, что классы с юнит-тестами оканчиваются на * Test

Maven традиционно располагает тесты в каталоге src / test , в то время как основной исходный код располагается в src / main . Разумеется это всего лишь договорённость, используемая в maven по умолчанию, и тесты и код можно располагать любым удобным образом.

Название тестовых методов так же могут быть любыми, однако для повышения читаемости кода, рекомендуется начинать их с префикса test * и отражать в названии суть теста.

Первый юнит-тест

В первом юнит-тесте строка

и есть входные данные, которые мы отдаём в проверяемую функцию.

Эталонные данные определены в следующей строке:

Вызываем проверяемый код и сохраняем результат его работы:

Наконец самая главная часть теста, проверка:

assertEquals сравнивает эквивалентность объектов expected и actual и, в случае когда они не эквивалентны, проваливает тест и выводит сообщение "Unexpected string value" . Функции assert * можно использовать и без сообщения:

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

Разработчики обычно пишут юнит-тесты только для предусмотренных разработчиком/архитектором/документацией/etc вариантов поведения функции. Для
StringUtils . fromDouble ( ) документация указывает что функция должна преобразовать цисло с плавающей запятой в строку.
Юнит-тест этой функции покрывает только описанный функционал. Цель юнит-тестирования — убедиться, что функция работает правильно, а не искать условия,
в которых она работает неправильно.

Более того, сам юнит-тест уже является краткой и понятной документацией к функции. В четырёх строках чётко и однозначно написано, как ведёт себя функция: возвращает новый строковый объект, значение которого является переданным ей числом с плавающей запятой, записанное в десятичной системе счисления.

А самый главный бонус юнит-тестирования, это фиксация поведения кода. Вы знаете, прямо сейчас, что функция ведёт себя определённым образом. И код, который её использует, полагается на это поведение. Если Когда вы захотите изменить эту функцию, юнит-тест будет вам гарантировать, что
поведение функции осталось таким же (либо тест провалится). Следовательно остальной код не заметит изменения реализации функции, а это значит, что с этого момента вы можете спокойной менять любую часть кода: юнит-тесты не позволят вам что-нибудь сломать.

Второй юнит-тест

Следующий юнит-тест напишем для обратной функции преобразования строки в число с плавающей запятой:

Читайте также:  Hp probook 4330 s

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *