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

    Как и обещал, я начинаю цикл статей, на тему 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

    На сегодня все, этого должно быть достаточно, что бы начать писать свои тесты для моделей.
    В следующих статьях, я рассмотрю создание тестов для Контроллеров и Представлений.

    Похожие публикации

    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 12

      +1
      Из замечаний:
      1-й it совершенно не очевиден, я бы его обозвал «should require name»
      2-й it что вообще проверяет? правильную работу ActiveRecord'а? Так он сам отспекан уже, это не ваша задача — его проверять.

      Из пожеланий:
      Последняя мода в ruby-community не юзать фикстуры (они ж реально неудобные, особенно, когда модель сложная и нужно прописать в ней кучу ассоциаций, поэтому посмотрите в сторону github.com/thoughtbot/factory_girl/tree/master
        0
        1 изменил, так наверно и вправду лучше, насчет второго, это просто для примера, что бы понять как работают фикстуры.
          0
          ну тогда пример неудачный, кто-то подумает, что так и надо тестить
          можно создать две фикстуры: valid и missing_name и на них показать работу фикстур, если уж так хочется
          0
          Поддерживаю. Оба теста занимаются проверкой AR, что в 90% случаев не нужно, даже в качестве примера. Я иногда пишу тесты, проверяющие AR, но только чтобы убедиться, что я нигде не ошибся в описании модели (например когда у меня сложные ассоциации). Потом эти тесты я обычно удаляю.

          По поводу фикстур зря вы: я бы порекомендовал посмотреть примочки типа nested_scenarios — делает работу с фикстурами удовольствием.
          +2
          Может перенести статью в блог Ruby?
            0
              0
              но Rails < Ruby, если нет блога по Rails, логичнее же в Ruby, чем в своем блоге
                0
                Rspec вещь универсальная, тут Rails больше для примера, т.к. если справится с тестами на них, то потом уже что угодно тестировать можно, подход мало изменится.
              –1
              наконец-то, читаем…
                0
                И еще лучше придерживаться какого-то одного стиля. Либо it «should require», либо 3-е лицо единственное число it «requires». А у вас в двух тестах по разному.
                  0
                  Почему сразу не autotest настроить?
                  Не понятно, зачем фикстуры то? Бла-бла-бла и прочую рыбу можно и на лету генерить.
                    0
                    А еще есть тема применить shoulda, они планируют всякие вкусны матчеры запустить под rspec giantrobots.thoughtbot.com/2009/2/3/speculating-with-shoulda

                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                    Самое читаемое