четверг, 28 апреля 2011 г.

Настройка rspec с autotest и spork

Цель
Настроить тестирование приложения Rails 3. Инструмент для тестирования должен обладать следующими свойствами:

  1. Выполнение тестов автоматически после сохранения любого файла проекта. Что бы не приходилось после каждого сохранения лезть в консоль и запускать тесты вручную.
  2. После выполнения тестов, будет показывать уведомление с результатами. Что бы не ждать выполнения тестов, а продолжать работу.
  3. Выполнение тестов должно происходить как можно быстрее. Думаю тут всё понятно.
 Что будем использовать

  1. Тестировать будет через Rspec. Считай стандарт для тестирование приложений и библиотек Ruby.
  2. Для автоматизации тестирования будем использовать autotest. Запускается в отдельной консоли и выполняет тесты, после сохранения файла проекта. Причём выполняет не все тесты, а только те, результат выполнения которых мог поменяться.
  3. Уведомления будет отображаться с помощью test_notifier. Отображает уведомление с результатами тестов, стандартными средствами ОС.
  4. Для ускорения будем использовать Spork. Тоже запускается в отдельной консоли, загружает Rails окружение и даёт к нему доступ по сети. И autotest, после настройки, сможет его использовать.

Установка

Если содаётся новое приложение, то можно сразу отказаться от стандартного инструмента для тестирования. Для этого в консоли при создании приложения нужно добавить параметр --skip-test-unit. Например:

rails new NewAppName --skip-test-unit

Далее в нужно добавить в Gemfile:

group :test do
  gem 'rspec-rails'
  gem 'autotest'
  gem 'spork', '~> 0.9.0.rc8'
  gem 'test_notifier'
  gem 'database_cleaner'
end

И установить необходимые гемы:

bundle install

Настройка

Первым делом займёмся Rspec. Тут всё просто, нужно в консоли набрать:

rails g rspec:install

Теперь настроим autotest и test_notifier. Для этого нужно в корне проекта создать файл .autotest. Например его можно создать командой:

touch .autotest

В файл .autotest нужно записать:
# encoding: utf-8   
# Подключаем test_notifer   
require "test_notifier/runner/autotest"
 
Autotest.add_hook :initialize do |at|
    # Добавляем в исключения репозиторий mercurial
    at.add_exception(%r{^\./\.hg})
    # Для любителей git'а
    # at.add_exception(%r{^\./\.git}) 
end

Чтобы после прохождения тестов появлялось уведомление необходимо установить системный пакет libnotify-bin. Под ubuntu он ставится так:

sudo apt-get install libnotify-bin

На очереди Spork. Для начала в консоли введём:

spork --bootstrap

Эта команда добавляет в начало файла spec/spec_helper.rb два блока:

Spork.prefork do
  # Этот блок выполняется единожды при запуске автотеста
end

Spork.each_run do
  # Этот блок выполняется перед каждой серией тестов
end

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

Должно получиться что то вроде:

require 'spork'

Spork.prefork do
  ENV["RAILS_ENV"] ||= 'test'
  require File.expand_path("../../config/environment", __FILE__)
  require 'rspec/rails'
  require 'database_cleaner'

  # Requires supporting ruby files with custom matchers and macros, etc,
  # in spec/support/ and its subdirectories.
  Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

  RSpec.configure do |config|
    config.mock_with :rspec
  end
end

Spork.each_run do
  load Rails.root.join("config/routes.rb")
  Dir[Rails.root.join("app/**/*.rb")].each { |file| load file }
end

И в файл .rspec нужно добавить строку:

--drb

Это на сколько я понял нужно что бы rspec смог присоединяться к spork.

Запускаем

Сначала проверим работоспособность Spork. Для этого создадим пустой тест. Создадим файл spec/models/test_spec.rb со следующим содержимым:

require 'spec_helper'

describe 'test' do
  it 'test1'
end

Теперь запустим одиночный тест с измерением времени:

time rake spec

У меня эта команда выдала:

real    0m14.643s
user    0m12.053s
sys     0m1.400s

Теперь запустим Spork. Для этого откроем новое окно консоли и набираем:

spork

И подождём пока не выведится:

Spork is ready and listening on 8989!

Теперь в первом окне консоли запускаем тест:

time rake spec

У меня получился следующий результат:

real    0m8.332s
user    0m5.860s
sys     0m0.844s
javascript:void(0)

Ускорение почти в два раза, с 14.6 до 8.3 секунд. В автотесте прирост будет ещё больше.

Ну и собственно запустим автотест. Для этого в первом окне наберём:

autotest

После старта должны прогнаться тесты. И в конце тестов должно появится уведомление.

Так это выгладит в Ubuntu

Для проверки можно изменить и сохранить файл spec/models/test_spec.rb. Тесты должны запустится автоматически и по окончанию должно опять появится уведомление.

Для остановки autotest нужно в соответствующей консоли нажать ctrl+z. Для ручного запуска тестов нужно нажать ctrl+c. Для остановки Spork, нудно в его консоли нажать ctrl+c.

Важное дополнение от 03.05.2011

Перезагрузка файлов приложения из папки app происходила не верно. Что бы это исправить нужно в файле config/environments/test.rb заменить строку:
config.cache_classes = true
заменить на:
config.cache_classes = false

Ещё исправил обновил файл spec/spec_helper.rb. Теперь не будет при каждом тесте сообщений об устаревшей константе RAILS_ROOT.

Второе обновление от 29.06.2011


Добавил пару важным моментов, упущенные в первой версии статьи. За напоминание спасибо Psylone.

3 комментария:

  1. Прекрасная статья! Респект автору!

    P.S. В моем случае (Ubuntu 10.10, Rails 3.0.7) пришлось поставить sudo apt-get install libnotify-bin и еще указать в Gemfile gem 'database_cleaner', т.к. изначально его не было.

    А так все ок :)

    ОтветитьУдалить
  2. Psylone, да я забыл это добавить. Это важные компоненты. Как появится время постараюсь добавить это в пост.

    ОтветитьУдалить
  3. Спасибо все получилось! Видимо плохо читал: http://russian.railstutorial.org/chapters/static-pages#top

    ОтветитьУдалить