ZenTest autotest и Mac OS X Leopard.
Вернемся к используемым инструментам. Для запуска тестов и спек я снова начал активно использовать autotest. Отказаться от него пришлось из-за того, что для определения того, что какие-то файлы в рабочей папке обновились, он использовал polling. Т.е. с огромной скоростью снова и снова опрашивал файловую систему на предмет обновления файлов, что на медленном диске в ноутбуке здорово замедляло работу всех программ.
Но спасибо хорошим разработчикам из Apple, которые в леопарде добавили API для работы с файловой системой через события (FSEvents). Благодаря им и Свену Швину (Sven Schwyn), который написал расширение autotest-fsevent. Оно учит autotest использовать FSEvents вместо постоянного опроса файловой системы.
Чтобы активировать это полезный функционал вам понадоббится Mac OS X Leopard. Устанавливаете гем
sudo gem install autotest-fsevent
Затем добавляете в файл ~/.autotest
require 'autotest/fsevent'
И радуетесь вернувшейся производительности.
Прочитать больше можно в блоге Свена.
autotest
Если вы пишете для своего кода на Ruby тесты либо спеки, то вам непременно пригодится autotest из гема ZenTest. Эта утилита запускается из корня проекта и следит за изменениями в тестах/спеках. Если таковые имеются, то она запускает только эти измененные файлы. За счет этого достигается скорость тестирования (прогонять переиодически кучу тестов — не быстрое занятие), и мы всегда знаем, когда у нас что-то сломалось.
Для этой утилиты существует плагин RedGreen, который подсвечивает зеленым или красным результаты прогона тестов, дабы одного взгляда хватило, чтобы увидеть ситуацию. Однако этот плагин не работает при тестирвоании спек, так как у них отличается формат вывода сообщения об ошибках. Если поместить следующий код в файл .autotest в вашем корневом каталоге или в каталоге с проектом, откуда запускаем тесты, то все будет работать как хочется.
module Autotest::RedGreen
BAR = "=" * 80
Autotest.add_hook :ran_command do |at|
# was if at.results.last =~ /^.* (\d+) failures, (\d+) errors$/
# changed because if we have pendings, output will look like "5 examples, 1 failure, 2 pending"
# and this condition will not work
if at.results.last =~ /^.* ((\d+) failures?|(\d+) errors?)/
code = ($2 != "0" or (not $3.nil? && $3 != "0")) ? 31 : 32
puts "\e[#{code}m#{BAR}\e[0m\n\n"
end
end
end