Rails, state_machine, Rspec, capybara, factory_girl, spork и другое. Часть III.

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

22. И начнём с «фабричных девчёнок: factory_girl. Этот замечательный gem необходим для того, чтобы упростить создание примеров объектов, которые используются в тестах. Например, чтобы каждый раз не создавать и не повторяться в разных тестах при создании нового пользователя, можно отлично использовать factory_girl. Итак, создадим файл spec/factories.rb для начала следующего содержания:

FactoryGirl.define do 

factory :user do

name ‘none’

email ‘none@example.com’

password ’1111111111′

end 

end

Здесь мы задали параметры для вновь создаваемого пользователя. Не забудьте добавить в spec/spec_helper.rb:

require ‘factory_girl’

23. Теперь открываем файл spec/models/user_spec.rb. Сейчас он должен быть практически пустым:

require ‘spec_helper’

 describe User do

 end

Теперь вставим следующий фрагмент кода сразу же за директивой  describe User do:

before(:each) do

user = Factory(:user)

end

Данный блок, как следует из его названия и определения, перед (before) каждым (each) тестом создавать нам пользователя, которого мы можем использовать в тестах.

24. Давайте напишем первые наши тесты. Сразу же за блоком before пишем следующее:

it ‘should create a new user with state new’ do

newuser = User.new(@user)

newuser.new?.should be_true

end

 it ‘should create a new user with state not eq active’ do

newuser = User.new(@user)

newuser.active?.should be_false

end

 it ‘should create a new user with state not eq blocked’ do

newuser = User.new(@user)

newuser.blocked?.should be_false

end

Все тесты имеют одинаковую структуру:

it ‘ожидание от теста’ do

выполнение каких-либо действий, проверок

end

Первый наш тест создаёт нового пользователя и проверяет его состояние — оно должно быть new:

newuser.new?.should be_true

Не удивляйтесь и не пугайтесь, если эта запись немного не понятна. Что вообще за «new?» и откуда оно взялось? Всё по порядку, позже объясню. Эту запись можно переписать другим способом, даже более понятным образом:

newuser.state.should eq(«new»)

Это как-то больше похоже на человеческий язык, правда, английский: «статус созданного пользователя должен быть эквивалентен новому».  Для задания и изменения статуса мы будем использовать замечательный gem state_machine.  Если кто-нибудь из читателей знаком с понятием «конечные автоматы», то ничего нового он не узнает. Для тех же, кто не в курсе, то state_machine — это способ описания состояний автомата, в нашем случае — это записи в таблице User, а так же методы перехода из одного состояния в другое.

Так как это не настоящее приложение, а так, для потренироваться, то я предположил, что Пользователи будут иметь всего три состояния:

1. new — это только что созданный пользователь

2. active — это пользователь, который активированный и может выполнять какие-либо действия

3. blocked — это заблокированный пользователь, соответственно, он ничего не может сделать

Это, иными словами, описание состояний автомата. Чуть позже опишу о способах изменения состояния, а пока обращаю Ваше внимание, что приведённые выше тесты не проходят, да… Что ж, давайте мелкими шажками делать, чтоб эти тесты проходили (-:

25. Описание state_machine очень неплохо документировано, настоятельно рекомендую ознакомиться с содержимым сайта. Я же предлагаю открыть открыть файл нашей модели app/models/user.rb и вписать туда следующее:

state_machine :initial => :new do

end

Этим самым мы описываем начальное состояние нашего конечного автомата. По умолчанию state_machine как раз и использует поле state, которое мы указали при генерации модели. Как видно из приведённой выше записи, начальное состояние будет «new». Но это ещё не всё (-: Кроме задания первоначального состояния в «new», state_machine даёт нам в помощь некоторые вспомогательные методы, которые дают нам возможность проверить состояние автомата. Один из них «new?», который возвратит «истина», если, как говорят у нас в Одессе, «состояние таки да new», и «ложь», если какое-то другое. Именно этот метод мы использовали в выражении «newuser.new?.should be_true«: а правда ли, что состояние нового пользователя есть «new»? (-: Ну что-то типа того.

26. После сохранения внесённых изменений, первый наш тест должен проходить! Ура, товарищи! (((-: Но только один из трёх… на оставшиеся должно выдавать ошибку, что-то типа этой:

1) User should create a new user with state not eq active

Failure/Error: newuser.active?.should be_false

NoMethodError:

undefined method `active?’ for #<User:0xb09a500>

# ./spec/models/user_spec.rb:23:in `block (2 levels) in <top (required)>’

Надо с этим что-то делать (-: А сделать надо простою вещь: добавить в наш файл модели две строчки

state :active

state :blocked

Иными словами, описать ещё два доступных состояния, которые мы пытаемся проверить во 2м и 3м тестах. После сохранения файла модели, все тесты должны пройти успешно!

В следующий раз я продолжу написание тестов и дальнейшее развитие нашего проекта.

Недавние записи

2 комментария to “Rails, state_machine, Rspec, capybara, factory_girl, spork и другое. Часть III.”

  1. Misha Says:

    Нужно детальней прописать, что state [:active, :blocked] нужно писать в блок state_machine {} do .. end

    class User :new do
    state :active
    state :blocked
    end
    end

    Вообщем очень помогла еще дока /path/to/ruby/gems/state_machine-1.1.0/lib/state_machine/machine.rb

    ЗЫ спасибо за статьи.

  2. Misha Says:

    Ваша система комментов жрёт код О_о
    между class User и :new do
    стояло это
    »
    левая стрела ActiveRecord::Base
    state_machine :initial =права стрела
    »
    может ваш XSS протект перестарался :-)

Оставить комментарий