RubyMineでやってみた:『スはスペックのス 【第 1 回】 RSpec の概要と、RSpec on Rails (モデル編)』


Component version
RubyMine 5.0(Windows)
Rails 3.2.12
Rspec 2.13.0

Setup

  1. 最初にプロジェクトを作るときに「Skip Test:Unit files」をチェックする。

  2. コードを書く

Gemfile
...
gem "rspec-rails", :group => [:development, :test]
...
  1. bundle install

  2. Tools > Run Rails Script > "rails", "generate rspec:install"

  3. Tools > Run Rails Generator > model > Blog name:string

  4. mkdir spec/fixtures

  5. コードを書く

spec/fixtures/blogs.yml
one:
  id: 1
  name: 今日の出来事その1
two:
  id: 2
  name: 今日の出来事その2

書式はこんな感じ:

データ名1:
  id: 1
  要素名: 内容
データ名2:
  id: 2
  要素名: 内容
.
.
.

データ名はテスト時にどのデータを取得するかのシンボルになる。
フィクスチャをテスト時に読み込むときは describe ブロックの中で呼び出せばいい

describe モデルクラス do
  fixtures :フィクスチャファイルの名前のシンボル
end

すべてのフィクスチャを読み込みたい場合は

fixtures :all
  1. Tools > Run Rake Task > db:migrate

  2. Run > Run > spec

  3. Toggle auto-test

1st red

  1. テストを追加する
spec/models/blog_spec.rb
# encoding: utf-8
require 'spec_helper'

describe Blog do
  subject{@blog = Blog.new}
  context "#title が設定されていない場合:" do
    it{should_not be_valid}
  end
end
  1. 保存すると自動でテストが走り、こける

  2. バリデーションを追記

app/models/blog.rb
...
validates :name, presence: true
...
  1. 保存すると自動でテストが走り、合格する

  2. テストを追加する

spec/models/blog_spec.rb
...
    it{should have(1).errors_on(:name)}
...
  1. 保存すると自動でテストが走り、合格する

2nd red

  1. テストを追加する
spec/models/blog_spec.rb
describe Blog do
  fixtures :blogs, :entries
  context "fixtureを使った場合:" do
    subject{@blog = blogs(:one)}
    it{should have_at_least(2).entries}
  end
end
  1. 保存すると自動でテストが走り、こける

  2. Tools > Run Rails Generator > model > entry title:string body:text posted_on:date created_at:timestamp updated_at:timestamp blog_id:integer

  3. Tools > Run Rake Task > db:migrate

  4. コードを書く

spec/fixtures/entries.yml
earliest:
  id: 1
  blog_id: 1
  title: "吾輩は猫である"
  body: "名前はまだない"
  posted_on: 2012-05-01
latest:
  id: 2
  blog_id: 1
  title: "hoge"
  body: "hogehoge"
  posted_on: 2012-05-10
_upgrading:
  id: 3
  blog_id: 2
  title: "fuga"
  body: "fugafuga"
  posted_on: 2012-06-01
  1. コードを書く
app/models/blog.rb
...
has_many :entries
...
  1. Run > Run > specすると、テストを通過する

3rd red

  1. テストを追加する
spec/models/entry_spec.rb
# encoding: utf-8
require 'spec_helper'

describe Entry do
  fixtures :entries, :blogs
  context "fixtureを使った場合:" do
    subject{@blog = entries(:earliest).blog}
    it{should == blogs(:one)}
  end
end
  1. 自動的にテストが走り、コケる

  2. コードを書く

app/models/entry.rb
...
  belongs_to :blog
...
  1. 保存すると自動でテストが走り、合格する

4th red

  1. テストを追加する
spec/models/blog_spec.rb
describe Blog do
  fixtures :blogs, :entries
  context "に記事を投稿できた場合:" do
    before{@blog = blogs(:one)}
    it "記事の件数が1件増えること" do
      lambda {
        @blog.entries.create(
            :title => 'new_post', :body => 'hello',
            :posted_on => Date.today)
      }.should change(Entry, :count).by(1)
    end
  end
end
  1. 保存すると自動でテストが走り、こける

5th red

  1. テストを追加する
spec/models/entry_spec.rb
describe Entry do
  fixtures :blogs
  context "#posted_on が入力されずに保存された場合:" do
    subject do
      @entry = Entry.new(title: "タイトル", body: "本文")
      @entry.save!
      @entry.reload
      @entry
    end
    its('posted_on') { should == Date.today }
  end
end
  1. 保存すると自動でテストが走り、こける

  2. コードを書く

app/models/entry.rb
class Entry < ActiveRecord::Base
  attr_accessible :blog_id, :body, :created_at, :posted_on, :title, :updated_at, :blog
  belongs_to :blog
  before_save :posted_on_today

  def posted_on_today
    self.posted_on = Date.today
  end
end
  1. 保存すると自動でテストが走り、合格する

6th red

  1. テストを追加する
spec/models/entry_spec.rb
describe Entry do
  fixtures :blogs
  context "#posted_on を明示して保存された場合:" do
    subject do
      @posted_on = Date.today - 10
      @entry = Entry.new(title: "タイトル",
                         body: "本文",
                         posted_on: @posted_on
      )
      @entry.save!
      @entry.reload
      @entry
    end
    its('posted_on') { should == @posted_on }
  end
end

  1. 保存すると自動でテストが走り、こける

  2. コードを書く

app/models/entry.rb
# self.posted_on = Date.today
self.posted_on ||= Date.today
  1. 保存すると自動でテストが走り、合格する

モデル編おしまい。


ブログやってます:PAPA-tronix !