среда, 23 июня 2010 г.

Фитнесс для питона

Однажды мы создалии для своего проекта на работе систему автоматизированного тестирования, которая могла бы в тестовых целях заменить нам программу управления. Система получилась тяжелая и плохо переносимая. Она была написана на перле, но в качестве транспортного уровня использовала код из продукта, который нормально собирается, по моему, только на 32-х битной FreeBSD. Транспортная библиотека из продукта с помощью swig была адаптирована для использования с perl. Кроме того на уровне perl по каждой функции существовала обертка...

Чтобы добавить функцию в эту систему необходимо было расширить транспортный уровень, доработать swig интерфейс, доточить perl враппер, отладиить все это (что порою превращалось в весьма нетривиальную операцию)..

Я уже знал в то время про FitNesse, и мне думалось, что неплохо было бы через wiki интерфейс управлять системой. Но связать все это вместе было достаточно нетривиально. Сам я на FreeBSD не сижу, а тестовое приложение не сидит на моей системе... А на той фре, на которой сидит тестовое приложение нет в помине никакой java, так нужной фитнессу.

Это все была присказка, переходим к сказке...

Поскольку собрать настроить и запустить систему тестирования было делом весьма неординарным, не удивительно, что никто ею и не пользовался.

С подачи Блейза, я тем временем заинтересовался питоном. Кроме того сам он сгенерировал набор классов транспортного уровня на чистом питоне. И я подумал что пора вдохнуть в систему тестирования новую жизнь. Мне понравилось, и я подумал еще и о том, что применение чистого python открывает широчайшие возможности в применении системы, в частности ее можно запустить на Windows. А так же, оценивая широчайшие возможности, я вспомнил про FitNesse, и решил что это хорошая возможность попробовать этого зверя в действии.

Установить FitNesse не просто, а очень просто... Скачиваем с сайта java приложение, в свободном каталоге, где фитнесс будет складывать свои файлы, запускаем.
$ java -jar fitnesse.jar -p 8000
Порт лучше указать, потому что по умолчанию он захочет использовать порт 80, для использования которого требуются права администратора.
После этого берем броузер и открываем http://localhost:8000/. Фитнесс запущен и готов к работе, авторизации по умолчанию он не требует.

Теперь переходим к питону. Поскольку вся система изначально разрабатывалась для java, она полностью пропитана java-терминологией. В частности путь к модулям традиционно для джавы называется CLASSPATH. Но давайте попорядку.

FitNesse родился на основе технологии FIT, которая подразумевает хранение сценариев в обычных файлах. Задачей FitNess'а был запуск FIT с указанием конкретных сценариев для выполнения. Но этот механизм был пересмотрен, в результате чего родилась технология SLIM. Отличие от FIT состоит в том, что SLIM сервер взаимодействует с сервером FitNesse через сокет. Как утверждается на сайте это позволяет избежать каких-то лицензионных ограничений, я в лицензиях не силен. Но с другой стороны понятно, что возможности у такого взаимодействия шире.

Итак мы собираемся использовать SLIM. Для тестирования python модулей нам нужен питоновый SLIM. Который называется waferslim. Его достаточно распаковать в любое место, при этом просто придется дополнительно указать дополнительный путь к модулям. Но проще установить его в систему, тогда он будет доступен по умолчанию. В своей Gentoo я для этого создал специальный ebuild.

Теперь переходим к конфигурированию FitNesse. Поскольку я пока не собираюсь смешивать языки - я настраиваю его централизованно. Это делается через http://localhost:8000/root. Там необходимо прописать примерно следующее:
!define TEST_SYSTEM {slim}
!define CLASSPATH_PROPERTY {PYTHONPATH}
!define COMMAND_PATTERN {python2 -m waferslim.server}
Далее мы погружаемся в изучение wiki синтаксиса и формата SLIM таблиц. Методика тестирования кода через FitNesse подразумевает очень конкретное разделение функций. Проще всего когда каждая функция принимает только один параметр или возвращает его. Хотя через Script таблицу можно использовать достаточно произвольный код, но decision таблицы выглядят попроще.

Для адаптации своего кода к возможностям FitNesse можно использовать специально заточенные классы фикстур.

Небольшой пример теста:
!path /home/dron/prog

|import|
|fixture|

!|fixture.Config|
|name|getName?|
|test|test|
|changed|changed|
После нажатия на кнопку Test, FitNesse запускает SLIM сервер, который подключается к FitNesse серверу по указанному адресу и порту и начинают свой тестовый диалог. В процессе этого диалока он подгружает тестируемые мной модули и выполняет записанный в таблицах сценарий. Результаты (зеленое/красное - хорошо/плохо) сразу же отображаются в окне броузера.

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

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