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」をチェックする。

1. コードを書く

```ruby:Gemfile
...
gem "rspec-rails", :group => [:development, :test]
...
```

1. bundle install

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

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

1. mkdir spec/fixtures

1. コードを書く

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

書式はこんな感じ：

```yaml
データ名１:
  id: 1
  要素名: 内容
データ名２:
  id: 2
  要素名: 内容
.
.
.
```

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

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

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

```ruby
fixtures :all
```

8. Tools > Run Rake Task > db:migrate

1. Run > Run > spec

1. Toggle auto-test

## 1st red

1. テストを追加する

```ruby: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. 保存すると自動でテストが走り、こける

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

```ruby:app/models/blog.rb
...
validates :name, presence: true
...
```

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

1. テストを追加する

```ruby:spec/models/blog_spec.rb
...
    it{should have(1).errors_on(:name)}
...
```

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

## 2nd red

1. テストを追加する

```ruby: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. 保存すると自動でテストが走り、こける

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

8. Tools > Run Rake Task > db:migrate

1. コードを書く

```yaml: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. コードを書く

```ruby:app/models/blog.rb
...
has_many :entries
...
```

1. Run > Run > specすると、テストを通過する

## 3rd red

1. テストを追加する

```ruby: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. 自動的にテストが走り、コケる

1. コードを書く

```ruby:app/models/entry.rb
...
  belongs_to :blog
...
```

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

## 4th red

1. テストを追加する

```ruby: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. テストを追加する

```ruby: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. 保存すると自動でテストが走り、こける

1. コードを書く

```ruby: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. テストを追加する

```ruby: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. 保存すると自動でテストが走り、こける

1. コードを書く

```ruby:app/models/entry.rb
# self.posted_on = Date.today
self.posted_on ||= Date.today
```

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

モデル編おしまい。

-----
ブログやってます：[PAPA-tronix !](http://weed.cocolog-nifty.com/wzero3es/)