Введение в JUnit

Часть первая: начинаем знакомство

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


Вступление

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

Впрочем, это всё в некотором роде лирика, за которую меня часто ругают, а также за то, что в моих статьях мало конкретики. Поэтому я решил исправиться и рассказать про инструмент, применяемый для unit-тестирования в реальной практике. Называется этот инструмент JUnit, а предназначен он для модульного тестирования программного кода, написанного на Java.

Почему именно JUnit, можете спросить вы. Дело в том, что Java - чрезвычайно распространённый язык программирования, имеющий достаточно простой синтаксис для понимания даже тем человеком, который использует в своей повседневной работе какой-то другой язык. Ко всему прочему, Java, как классический объектно-ориентированный язык, даёт отличное представление обо всех сильных и слабых сторонах модульного тестирования, которые характерны и для других языков.


JUnit: краткая характеристика

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

Во-первых, стоит отметить, что JUnit относится к славному семейству программных продуктов с открытым исходным кодом, или, проще говоря, к open-source. Найти сам фреймворк, а также массу дополнительной информации о нём можно на официальном сайте данного программного продукта junit.org.

JUnit предоставляет разработчикам не только средства непосредственного тестирования, но также и средства коллективной работы с данными, которые непосредственно связаны с тестированием, и средства для автоматической "прогонки" тестов (так называемые раннеры, от английского test runners). Фреймворк достаточно просто интегрируется с популярными средами разработки для Java-программистов (уж с Eclipse, по крайней мере, точно). Собственно, именно на примере его использования Eclipse мы с вами и будем обсуждать возможности (и особенности) данного фреймворка.


Итак, на старт!

Что ж, будем считать, что вы успешно скачали на свой компьютер дистрибутив JUnit'а, установили все нужные библиотеки в каталог с Eclipse и теперь просто-таки горите нетерпением что-нибудь потестировать. Что ж, давайте приступим.

Для начала вам, конечно, нужно будет создать какой-нибудь простой проект, чтобы на нём научиться тестировать. Достаточно буквально пары классов с буквально парой методов - чтобы разобраться в JUnit'е, этого хватит. Что именно делают эти классы и их методы, в общем-то, не так уж и важно, - главное, чтобы делали хоть что-нибудь, чтобы можно было протестировать, насколько хорошо они это делают.

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

Зайдя в пункт "File" главного меню Eclipse, затем зайдите в подменю "New", а в нём уже выберите "JUnit Test Case". Здесь вам потребуется указать некоторые особенности создаваемого класса теста в появившемся на экране окне. На стандартных вещах вроде Source folder или Package я останавливаться не буду, а вот на остальных - как раз напротив, остановлюсь. Супер-класс менять не стоит, класс для тестирования (class under testing) - это, как вы понимаете, тот самый класс, который мы и будем тестировать; что касается генерируемых методов, то пока, на первый раз, никакие из них можно вовсе и не генерировать. Далее вам нужно будет выбрать методы, которые должны будут подвергнуться тестированию. В том числе вам будут предложены и методы суперклассов тестируемого класса, которые, как правило, в тестировании уже особо не нуждаются, особенно если эти классы писали не вы, а кто-нибудь другой. Поэтому выберите один метод того класса, который написали вы сами для тестирования, - на первый раз этого вполне хватит.


Тестовые методы

После того, как вы кликнете "ОК" в диалоге создания нового теста, его код будет содержать конструкцию, которая автоматически заставит тест "завалиться" по причине того, что тест просто-напросто на самом-то деле ещё не написан. Выглядит же эта конструкция следующим образом: "fail("Not yet implemented");" (без кавычек в коде программы, конечно же). Понятно, что реальные тесты, которые сравнивают выходной результат того или иного метода с некоторым эталонным значением, не могут быть написаны с использованием исключительно данной несложной конструкции. Поэтому давайте познакомимся с методами, которые могут применяться для сравнения, опять-таки, результата с эталоном. Их достаточно много, но разобраться в них совсем не сложно.

Метод assertEquals сравнивает два значения (например, два целых числа), первое из которых является ожидаемым значением, а второе - реальным значением, получаемым в ходе работы программы. Для вещественных чисел можно также задать точность, с которой будет выполняться сравнение (до десятых, до сотых и так далее). Естественно, что тест, применяющий такой метод, будет считаться успешно пройденным только в том случае, если эталонное и реально полученное в ходе выполнения тестируемого метода значения совпадут. Метод assertNull, как несложно догадаться по его названию, предназначен для сравнения исследуемого объекта со значением null, то есть, фактически, для проверки существования экземпляра какого-то класса (не обязательно того, который тестируется, более того, чаще всего как раз и не его). Есть и другой аналогичный метод, assertNotNull, который занимается похожей работой, но считается успешно пройденным при диаметрально противоположных условиях. Ещё два метода, которые сравнивают два объекта друг с другом - assertSame и assertNotSame.

У вас наверняка возникнет вопрос, чем именно метод assertEquals отличается от метода assertSame? Вопрос закономерный и совсем не праздный, потому что при неправильном выборе метода тест может попросту "завалиться" на ровном месте, даже если сам тестируемый класс отработает без каких бы то ни было нареканий. Дело в том, что метод assertSame сравнивает, фактически, не столько содержимое объектов, сколько сами объекты, то есть, если у вас два экземпляра класса фактически должны ссылаться на один объект, и вы хотите проверить, выполняется ли это, вам нужен именно данный метод. Если же вы хотите узнать, насколько два объекта похожи друг на друга именно, скажем так, содержанием, тогда вам нужен метод assertEquals.

Помимо этих методов, есть те, которые пригодятся при работе с логическими выражениями, методами или переменными - это assertTrue и assertFalse. В качестве параметра этим методам передаётся булевское выражение, которое затем проверяется, соответственно, на истинность или ложность. Ну и, конечно, есть ещё явным образом "проваливающий" тест метод fail, который уже был использован выше. Кстати, все методы позволяют добавлять поясняющую строку к тесту (как уже приводившийся fail) - она должна идти первым параметром.

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

Вадим СТАНКЕВИЧ,
dreamdrusch@tut.by

Версия для печатиВерсия для печати

Номер: 

44 за 2009 год

Рубрика: 

Software
Заметили ошибку? Выделите ее мышкой и нажмите Ctrl+Enter!