Средства тестирования в Ruby on Rails
Как известно, тестирование является одной из важнейших составляющих разработки приложений на основе Ruby on Rails. Поддержка тестирования была включена в Rails с самого начала, для этого использовалась библиотека Test::Unit. Однако, со временем, появилось много альтернативных средств для тестирования в Rails-приложениях.
В этой заметке я проведу небольшой обзор средств, используемых в настоящий момент для тестирования приложений на базе Ruby on Rails. Я не ставлю себе целью выбрать “лучшее” – я считаю, что этот выбор должен делать каждый сам, однако я попытаюсь показать различные варианты – чтобы было из чего выбирать.
Модульные и функциональные тесты
Здесь я рассмотрю основные средства, используемые для модульного и функционального тестирования в Rails-приложениях. Напомню, что модульные тесты используются для тестирования логики приложения, которая расположена в моделях, а также для тестирования различных независимых участков приложения, например, хелперов (helpers).
Test::Unit
Test::Unit является классическим средством тестирования в стиле xUnit. В Rails-приложениях именно он и используется по умолчанию. Набор тестов с его использованием описывается в виде класса, методы которого представляют различные тесты. В коде методов в необходимых точках добавляются проверки, представленные вызовами assert_*.
Ниже приведен пример простейшего теста с использованием Test::Unit:
require 'test/unit'
class MyTest < Test::Unit::TestCase
# def setup
# end
# def teardown
# end
def test_fail
assert(2 + 2 == 4, 'Assertion was false.')
end
end
RDoc-документация для Test::Unit: http://www.ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit.html
RSpec
RSpec - средство, предназначенное для спецификации поведения кода. Я не хочу вдаваться в отличия спецификации от тестирования (и BDD от TDD), просто приведу пример спецификации модели с использованием RSpec:
describe "A new account" do
before do
@account = Account.new
end
it "should have a balance of $0" do
@account.balance.should eql(Money.new(0, :dollars))
end
end
Как видно из примера, RSpec представляет специальный язык в рамках Ruby для описания спецификаций. Следствием этого является то, что хорошо написанные спецификации легко читаются, практически как текст на английском языке.
Одним из минусов RSpec является то, что для проверки спецификаций требуются создавать специальные Rake-задачи в приложении, в отличии от тестов на основе Test::Unit, задачи для которого включены в Rails.
Сайт проекта: http://rspec.info
RDoc-документация для RSpec: http://rspec.rubyforge.org/rspec/1.2.8/
Test/Spec
Test/Spec предназначен для описания спецификаций, аналогичных RSpec на базе Test::Unit, что позволяет использовать те же самые стандартные задачи, что и для Test::Unit, а также совмещать тесты и спецификации.
require 'test/spec'
describe "Foo" do
it "should bar" do
(2 + 3).should.equal 5
end
end
Сайт проекта Test/Spec и RDoc-документация: http://test-spec.rubyforge.org/
Shoulda
Shoulda - это средство, которое работает на базе Test::Unit и предоставляет некоторые дополнительные возможности, в частности специальный язык для описания конструкций в тестах и набор макросов для часто используемых проверок:
class UserTest < Test::Unit::TestCase
should_have_many :posts
should_not_allow_values_for :email, "blah", "b lah"
should_allow_values_for :email, "a@b.com", "asdf@asdf.com"
should_ensure_length_in_range :email, 1..100
should_ensure_value_in_range :age, 1..100
should_protect_attributes :password
context "A User instance" do
setup do
@user = User.find(:first)
end
should "return its full name" do
assert_equal 'John Doe', @user.full_name
end
context "with a profile" do
setup do
@user.profile = Profile.find(:first)
end
should "return true when sent #has_profile?" do
assert @user.has_profile?
end
end
end
end
Update: В настоящий момент Shoulda может быть использована и вместе с RSpec
Сайт проекта: http://www.thoughtbot.com/projects/shoulda/
Remarkable
Shoulda показала удобство использования макросов для распространенных задач в тестировании, однако она работала только над Test::Unit. Remarkable - это реализация набора макросов, аналогичных Shoulda для RSpec. Его использование позволяет описывать следующие спецификации:
describe Post do
it { should belong_to(:user) }
it { should have_many(:comments) }
it { should have_and_belong_to_many(:tags) }
it { should validate_presence_of(:body) }
it { should validate_presence_of(:title) }
it { should validate_uniqueness_of(:title, :allow_blank => true) }
end
Сайт проекта Remarkable и RDoc-документация: http://remarkable.rubyforge.org/
Блог проекта: http://www.nomedojogo.com/category/remarkable/
Исходный код Remarkable: http://github.com/carlosbrando/remarkable/tree/master
Интеграционные тесты - Cucumber
Cucumber, используемый для интеграционного тестирования приложений продолжает движение в сторону читабельности тестов - тестовые сценарии описываются буквально на естественном языке:
Scenario: Add two numbers
Given I have entered 13 into the calculator
And I have entered 22 into the calculator
When I press "+"
Then the result should be 35 on the screen
И не только на английском:
Сценарий: Сложение двух целых чисел
Допустим я ввожу число 50
И затем ввожу число 70
Если я нажимаю "+"
То результатом должно быть число 120
Написание сценариев в таком виде делает Cucumber просто незаменимым инструментом для тестирования Rails-приложений. Разумеется, некоторое количество кода писать все-таки приходится, для того чтобы описать что означают те или иные приложения.
Заключение
Здесь я описал некоторые средства, используемые для тестирования Rails-приложений. Я сознательно не затрагивал здесь различные библиотеки для создания mock-объектов или замены fixtures, возможно, в дальнейшем им можно посвятить отдельную заметку.

on July 23, 2009 at 14:07 leopard wrote:
Мне так кажется, или кода как то не хватает.
on July 23, 2009 at 14:07 leopard wrote:
Уже решил проблему - вырубил js.
on July 23, 2009 at 15:07 Somebody32 wrote:
Хочется дополнить, что шулда прекрасно умеет работать с rspec.
on July 24, 2009 at 08:07 Alno wrote:
Спасибо за информацию, добавил.
on July 24, 2009 at 18:07 Нат wrote:
В самом деле, мне не совсем ясно, зачем использовать Remarkable, если есть Shoulda. Но это на любителя, в Remarkable есть очень красивый и элегантный метод писать спеки на контроллеры.