2 March 2009

RSpec. Часть #1: создаем тесты для модели

Ruby on Rails
Как и обещал, я начинаю цикл статей, на тему RSpec.

В этой статье, я постараюсь, подробно рассказать, как писать тесты для моделей в Ruby on Rails. Если вы уже знакомы с rspec_on_rails, поправьте и дополните меня, если что то не так. Помните, что я изучаю Rspec вместе с вами и могу где то ошибаться.

Подготовка


Будем считать, что прочитав мою предыдущую статью, вы уже создали тестовый проект, сконфигурировали его и создали для него схему в базе, а так же установили gem rspec. Если нет, быстро делаем:
[sudo] gem install rspec
rails ./test -d mysql
nano ./test/config/database.yml
rake db:create

Теперь, давайте перейдем в каталог нашего проекта и выполним команду:
./script/generate rspec

Теперь в корне нашего проекта, у нас есть директория spec. Можно создавать непосредственно тест для нашей модели, выполним:
./script/generate rspec_model Post

Rspec автоматом создаст саму модель, fixtures и migrates для нее, а так же файл теста, следующего содержания:
require File.dirname(__FILE__) + '/../spec_helper'

describe Post do
  before(:each) do
    @post = Post.new
  end

  it "should be valid" do
    @post.should be_valid
  end
end

Пример простого теста


Ну что, можно попробовать в первый раз прогнать все тесты, выполним:
rake spec:models

Ой ой ой, не прошло. Rspec говорит:
You have 1 pending migrations:
  20090302064129 CreatePosts
Run "rake db:migrate" to update your database then try again.

Ну что же, выполним то что нас просят, но до этого, давайте немного подправим файл миграции, до такого состояния:
class CreatePosts < ActiveRecord::Migration
  def self.up
    create_table :posts do |t|
      t.string :name, :limit => 50, :null => false
      t.text :content
      t.timestamps
    end
  end

  def self.down
    drop_table :posts
  end
end

Теперь прогоним мигрейты и снова запустим тест:
rake db:migrate
rake spec:models

и вуаля, наш тест успешно пройден(если у вас не так, пишите в комментариях, постараюсь помочь):
.

Finished in 0.040821 seconds

1 example, 0 failures

Точка в начале означает что тест пройден успешно, буква F означает что тест не пройден. Давайте теперь немного усложним наш пример. Изменим немного код:
it "should require name" do
  @post.name = nil
  @post.should_not be_valid
  @post.errors.on(:name).should_not be_nil
end

После выполнения мы получим:
F

1)
'Post «should require name»' FAILED
expected valid? to return false, got true
./spec/models/post_spec.rb:10:

Finished in 0.045391 seconds

1 examples, 1 failure
rake aborted!

Ок, пока все правильно, нужно добавить в нашу модель валидацию:
validates_presence_of :name
validates_length_of :name, :within => 3..50

Прогоняем еще раз, теперь все ОК. Тест прошел успешно.

Использование Fixtures


Давайте отредактируем файл ~/spec/fixtures/post.yml:
one:
  id: 1
  name: "this is ferst post"
  content: "tru la la, tra la la"
two:
  id: 2
  name: "this is second post"
  content: "tran tan tan, tra ta ta" 

Теперь изменим наш тест, до такого вида:
require File.dirname(__FILE__) + '/../spec_helper'

describe Post do
  fixtures :posts

  before(:each) do
    @post = Post.new
  end

  it "should require name" do
    @post.name = nil
    @post.should_not be_valid
    @post.errors.on(:name).should_not be_nil
  end

  it "clears post" do
    posts(:one).destroy
    lambda { posts(:one).reload }.should raise_error(ActiveRecord::RecordNotFound)
  end

end

Таким образом мы подгрузили все фикстуры(fixtures :posts) и работаем с ними уже напрямую, вызывая их по символам(posts(:one)), указанным в posts.yml

На сегодня все, этого должно быть достаточно, что бы начать писать свои тесты для моделей.
В следующих статьях, я рассмотрю создание тестов для Контроллеров и Представлений.
Tags: rails ruby rspec model bdd test spec gem rspec_on_rails
Hubs: Ruby on Rails
+12
32.4k 41
Comments 12
Ads