Юнит-тесты Delphi или разработка через тестирование
Разработка через тестирование в Delphi производится с помощью встроенного инструмента DUnit. В статье мы рассмотрим, как создаются тестовые проекты Delphi, как создавать юнит тесты и как тестировать.
Итак, сначала поговорим о том, что такое DUnit. DUnit – это инструмент тестирования с открытыми исходными кодами, основанный на JUnit. Доступен он как для Delphi, так и для C++.
Вообще, в состав Delphi этот инструмент включён начиная с Delphi 2005. Для Delphi и C++ Builder DUnit устанавливается автоматически установщиком RAD Studio. В папке \source\DUnit (внутри папки, куда установлен Delphi) вы можете найти много ресурсов, в том числе исходные файлы, документацию и примеры тестов. Поставляется DUnit под лицензией Mozilla Public License 1.1 (MPL).
В статье я не буду углубляться в теорию, а лишь покажу, как пользоваться инструментом DUnit в Delphi. Будем считать, что читатель знает, что такое разработка через тестирование.
Создание тестового проекта
Тестовый проект содержит один или несколько тестовых случаев, которые представляют из себя обычные .pas файлы и будут доступны в IDE на панели Project Manager. Также RAD Studio предоставляет в ваше распоряжение мастер создания тестового проекта «Test Project Wizard». Рекомендуется создавать два отдельных проекта: один тестируемый, а второй тестирующий. Так вам не придётся в будущем удалять ваши тесты из готового приложения.
Давайте для начала создадим проект, который мы будем тестировать. Допустим, это будет оконное VCL приложение. Выберите пункт меню «File -> New -> VCL Forms Application - Delphi». Созданный проект сохраните.
После создания тестируемого проекта, создадим тестовый проект. Для этого выберите пункт меню «File -> New -> Other...», затем в диалоге «New Items» выберите «Unit Test -> Test Project» и нажмите «OK».
На первом шаге мастера «Test Project Wizard» в поле «Source Project» можно указать тестируемый проект, если их несколько. В полях «Project Name» и «Location» указывается название и расположение тестового проекта. В поле «Personality» выбирается язык программирования (в нашем случае – это Delphi). Все перечисленные поля заполнились автоматически, что нам подходит. Галочку «Add to project group» оставьте, чтобы проект добавился в текущую группу проектов. Нажмите «Next >».
На следующем шаге можно выбрать, как будет выполняться тест (поле «Test Runner»): в окне («GUI») или в консоли («Console»). Оставим здесь предложенный по умолчанию вариант – «GUI». В поле «Test Framework» указываются инструменты тестирования. Поменять в этом поле ничего нельзя, т.к. для Delphi и C++ поддерживается только инструмент DUnit. Нажмите «Finish» и вы увидите, что в группе проектов появился новый пустой тестовый проект.
Тестовые случаи и тестирование
В типичном тестовом проекте, для каждого тестируемого класса есть тестирующий класс, но это не обязательно. Тестирующий класс также привязан к тестовому случаю. Как правило, тестирующий класс имеет набор из одного или нескольких методов, которые соответствуют одному или нескольким методам тестируемого класса. В один тестовый проект могут быть включены несколько тестовых случаев. Запуск каждого тестового случая и тестового проекта может быть автоматизирован с помощью bat-файлов или скриптов сборки проекта.
В основном рекомендуется создавать тесты в отдельном проекте (отдельно от тестируемого проекта). Так вам не нужно будет удалять тесты из проекта перед финальной сборкой проекта.
RAD Studio предоставляет вам мастер «Test Case Wizard» для помощи в создании тестовых случаев, которые вы сможете настроить на своё усмотрение.
Прежде чем сделать тестовый случай, давайте определимся, что мы будем тестировать. В тестируемом проекте Project1, который мы создали, есть форма. Давайте её и будем тестировать. Допустим, наша форма будет построчно сравнивать два текстовых файла и показывать строки с различиями. Сравнивать будем двумя способами: учитывая регистр и без учёта регистра. Код для теста сделаем элементарный, будем сравнивать строки с одинаковыми индексами.
Итак, на форму ставим два текстовых поля TRichEdit и две кнопки TButton. Затем обрабатываем события от нажатий кнопок и дописываем код следующим образом:
Как видите, по нажатию на кнопки будут вызываться две процедуры Compare и ShowDifferences. Первая процедура будет сравнивать два текста и сохранять индексы несовпадающих строк в список differentStrings, а вторая процедура будет на основе этого списка подкрашивать несовпадающие строки в красный цвет. В процедуру Compare будет передаваться параметр ignoreCase определяющий способ сравнения строк. Пока реализацию функции Compare делать не будем, а сразу сделаем тест для неё.
Для создания тестов нужно сделать следующие шаги:
-
-
-
- Откройте юнит, для которого нужно сделать тесты и переключитесь на закладку «Code». Т.е. ваш юнит должен отображаться в редакторе кода.
- Выберите пункт меню «File -> New -> Other...».
- В диалоге «New Items» выберите «Unit Tests -> Test Case» и нажмите «OK».
-
-
-
-
-
- В открывшемся мастере «Test Case Wizard» на первом шаге нужно указать путь к файлу тестируемого юнита в поле «Source file» (сюда автоматически подставляется путь к файлу для текущего открытого в редакторе юнита) и выбрать, какие классы и методы нам нужно тестировать. В нашем примере будем тестировать только один метод Compare, поэтому поставьте галочку только напротив него. Нажмите «Next >».
-
-
-
-
-
- На следующем шаге задаётся тестовый проект в поле «Test Project», имя файла тестового случая в поле «File name», инструменты тестирования в поле «Test Framework» (это поле неактивно, т.к. поддерживается только DUnit) и базовый класс в поле «Base class». Базовый класс TTestCase подходит для большинства случаев, но вы можете использовать и собственный класс. В нашем примере мы не будем здесь ничего менять. Нажмите кнопку «Finish».
-
-
После этого вы увидите, что в тестовом проекте появился файл «TestUnit1.pas» и в этот же проект добавлен тестируемый юнит «Unit1.pas».
А вот что вы увидите в файле TestUnit1.pas:
Как видите, здесь сделана заготовка для тестирующего класса TestTForm1, унаследованного от класса TTestCase. В секции initialization происходит регистрация этого класса.
В методе SetUp происходит подготовка к тестированию. Здесь нужно создать тестируемый класс и подготовить всё что нужно для тестов, например, подключиться к удалённому серверу или базе данных и т.п. Кстати здесь код сгенерирован с ошибкой: конструктор формы должен принимать входной параметр. Исправим строку кода с созданием формы следующим образом:
Метод TearDown вызывается по окончании тестирования и здесь нужно освободить все ресурсы и удалить все созданные объекты. Здесь сгенерированный код нас устраивает.
Метод TestCompare создан как раз для тестирования нашего метода Compare. Как видите, здесь вызывается наш метод Compare, но нет никаких проверок. Давайте добавим здесь в текстовые поля одинаковый текст, вызовем метод Compare и сделаем проверку результата.
После этого запустите тестовый проект Project1Tests.exe. Для этого сделайте его активным (дважды щёлкните по проекту в окошке «Project Manager») и затем запустите его выполнение (для этого выберите пункт меню «Run -> Run» или нажмите клавишу F9). После запуска перед вами появится окошко, показанное на картинке ниже.
Чтобы запустить все тесты выберите пункт меню «Actions -> Run». Если у вас много тестов, а вам нужно выполнить только часть из них, вы можете проставить галочки рядом с нужными тестами и затем вызвать пункт меню «Actions -> Run selected test». После выполнения тестов вы увидите нашу ошибку. Это нормально, ведь пока наша функция Compare не написана и она ничего не сравнивает. Если вы щёлкните на ошибку, то в нижнем поле увидите подробности.
Теперь давайте исправлять ошибки, чтобы тестирование прошло успешно. Допишите функцию сравнения следующим образом:
В методе тестирования добавим тесты для разных вариантов сравнения:
Теперь протестируем нашу функцию Compare. Как видите, всё работает правильно, ошибок нет.
Помимо метода CheckEquals в вашем распоряжении есть и другие методы для проверки результатов. Вот основные методы, которые вам могут понадобиться:
-
-
-
- Check – проверяет выполнение условия и кидает исключение, если условие не выполняется.
- CheckEquals – проверяет равенство двух значений и кидает исключение, если значения не равны.
- CheckNotEquals – проверяет неравенство двух значений и кидает исключение, если значения равны.
- CheckNotNull – проверяет указатель на «не nil» и кидает исключение, если указатель равен nil.
- CheckNull – проверяет указатель на nil и кидает исключение, если указатель не равен nil.
- CheckSame – проверяет равенство указателей на объекты и кидает исключение, если указатели не равны.
- Fail – просто кидает исключение ETestFailure с нужным вам текстом.
-
-
Тестирование приватных методов
Отдельно хотелось бы показать, как тестировать приватные методы. Для вызова приватных методов в Delphi мы воспользуемся RTTI (Run-Time Type Information).
Для начала перенесите объявление переменной differentStrings и методов Compare и ShowDifferences в секцию private и добавьте директиву $RTTI, которая даст доступ к приватным методам (к приватным переменным доступ через RTTI разрешён по умолчанию):
Код тестирования поменяйте следующим образом, не забыв добавить в секцию uses юнит System.Rtti:
Аналогично можно тестировать приватные свойства. Директива $RTTI будет выглядеть тогда следующим образом:
Итог
Итак, из статьи вы узнали, как реализована поддержка разработки с помощью тестирования в Delphi, а именно: как создавать тестовый проект, как создавать тесты и проводить тестирование, как тестировать приватные методы.
Комментарии
первым должен быть expected (ожидаемое значение), вторым - actual ("на самом деле"),
а у Вас наоборот...и тогда в сообщении о провале теста пишется неверное "ожидался 0, а было - 1", хотя должно "ожидалась 1, а было 0"
proghouse.ru/programming/56-dunit
дошел до того, что нужно скомпилировать после чего должно появится окошко DUnit: An Xtreme.. его у меня нету. Просто в низу пишет что успешно и все. Больше никаких признаков. Кто может помочь отпишите.
Вам нужно запустить тестовый проект. Вот цитата из статьи:
Цитата:
RSS лента комментариев этой записи