ゆうなんとかさんの雑記帳的な。

Twitterで踊ったり音ゲーしたりしてるあの名前がよくわからない人が書いてるらしいよ。

RSpec on Railsやってみた

いよいよ開発っぽいことをやりますがやっぱり当分は写経です。
今日はRubyist Magazine - スはスペックのス 【第 1 回】 RSpec の概要と、RSpec on Rails (モデル編)RSpec on Railsから始めます。
なお、Railsの準備は一応ひと通りやってあるので今回は省略します。それから、

RSpec プロジェクトのサイトでは、 RSpec on Rails をインストールする際には、RSpec 本体も Rails プラグインとしてイン ストールすることが推奨されています。

とは書いてあるものの、何のことやらよくわからなかったサクッとやってみたいので今回は他のGemとまとめてbundle installする方向でいきます。

前ふり

ここからかなり長い前ふりになります。本編はもう少し下です。

RSpec on Railをはじめる

今はここに載ってるコマンドとは違うんですよね。そうとは知らなかったので、

$ rails generate rspec
Could not find generator rspec.

はい、早速積みました。
前回、script/generateをrails generateに読み替えたらある程度うまく行ってたので今回もそうだろうと思ったらこれだよ!とりあえずrails generateとだけ打ち込んでみると

$ rails generate
Usage: rails generate GENERATOR [args] [options]

General options:
  -h, [--help]     # Print generator's options and usage
  -p, [--pretend]  # Run but do not make any changes
  -f, [--force]    # Overwrite files that already exist
  -s, [--skip]     # Skip files that already exist
  -q, [--quiet]    # Suppress status output

Please choose a generator below.
(中略)
Rspec:
  rspec:install
(後略)

とでてくるので、ここはrails generate rspec:installと打ち込むのが正解です。

$ rails generate rspec:install
      create  .rspec
      create  spec
      create  spec/spec_helper.rb

上に上げたページに載ってるのと比べると生成されるものが少ないですが、「きっと仕様が大幅に変わってるはず」なのでこのまま続けます。

モデルをつくる

現在のバージョンでは普通にモデルをつくるのと変りなくコマンドを打ち込めば、RSpecのテストスクリプトも生成されるようになってます。最初はHP通りにコマンド打ち込んでて詰んでました

$ rails generate model Blog name:string
      invoke  active_record
      create    db/migrate/20121014062104_create_blogs.rb
      create    app/models/blog.rb
      invoke    rspec
      create      spec/models/blog_spec.rb

とりあえず実行してみる…その前に

スキーマを少し変更しておきます。name属性をnot nullにしておきましょう。無題のブログというのはまずい気がします。

class CreateBlogs < ActiveRecord::Migration
  def change
    create_table :blogs do |t|
      t.string :name, :null => false

      t.timestamps
    end
  end
end

サンプルデータを用意する

その筋の言い方をすれば「フィクスチャ」というやつです。spec/fixtures/blogs.yml というファイルを作り、中身はこうしておきます。

$ cat ./spec/fixtures/blogs.yml
yuuxxxx:
  id: 1
  name: ゆうなんとかさんの雑記帳的な。
totoadad:
  id: 2
  name: ひづ・ふぃなーれ!

ちなみにid:2のブログはこちらです。

ここから本編

おまたせしました。いよいよテストコードと、それに通るコードを書いていきます。

それでは実行してみる

rake specで実行できるみたいです。それではやってみましょう。データベースのマイグレーションを済ませてから、*1

$ rake spec
NOTICE:  CREATE TABLEはシリアル列"blogs.id"用に暗黙的なシーケンス"blogs_id_seq"を作成します。
NOTICE:  CREATE TABLE / PRIMARY KEYはテーブル"blogs"に暗黙的なインデックス"blogs_pkey"を作成します
/usr/bin/ruby -S rspec ./spec/models/blog_spec.rb
*

Pending:
  Blog add some examples to (or delete) /home/Irish/myblog/spec/models/blog_spec.rb
    # No reason given
    # ./spec/models/blog_spec.rb:4

Finished in 0.00027 seconds
1 example, 0 failures, 1 pending

Randomized with seed 6639

保留中のテストがひとつだけあるみたいです。どうでもいいのですが保留中だとそのテストは黄色で表示してくれるので、背景色と若干かぶります。

テストを書く

それではテストを書きましょう。今回は「ななしのブログは許しません」、つまり、「nameが設定されていないのBlogオブジェクトのvalid?はfalseである」というテストを書きます。
写経してもよかったのですが、前々回のコメントにあったsubjectや、その他にもcontextというメソッドが何なのか、少し調べてみたので両方とも使ってみます。

require 'spec_helper'

describe Blog do
  context '#name が設定されていない' do
    subject { Blog.new }
    it { shold_not be_valid }
  end
end

超すっきり。シンタックスエラーで怒られてないということはこれでいいんですねではテストします。

$rake spec
(中略)
F

Failures:

  1) Blog#name が設定されていない 
     Failure/Error: it { should_not be_valid }
       expected valid? to return false, got true
     # ./spec/models/blog_spec.rb:7:in `block (3 levels) in <top (required)>'

Finished in 0.04853 seconds
1 example, 1 failure

Failed examples:

rspec ./spec/models/blog_spec.rb:7 # Blog#name が設定されていない

Randomized with seed 59430

rake aborted!
/usr/bin/ruby -S rspec ./spec/models/blog_spec.rb failed

Tasks: TOP => spec
(See full trace by running task with --trace)

当たり前ですが失敗です。それではこのテストが通るコードを書いていきます。

ではテストを通してみる

文量も結構いい感じなので、今日はこのテストをグリーンにしておしまいにします。コードや出力結果をぺたぺた貼っていくとすぐに文章量が増えていくので水増ししてるみたいであれですが…
先ほどのテストに失敗したのは、Blogクラスがバリデーションをしていないからでした。というわけでちゃんと設定されているか確認するように仕様を追加します。
app/models/brog.rbを以下のように書き換えます。

class Blog < ActiveRecord::Base
  attr_accessible :name
  validates_presence_of :name
end

これで仕様通りのはずなので、改めてテストします。めんどくさいのでテスト部分だけ。

.

Finished in 0.05562 seconds
1 example, 0 failures

Randomized with seed 13275

無事にグリーンになりました。今日はこれまで!

*1:なおさきほど、rakeとだけ打ち込むとマイグレーションとテストを連続で実行してくれることが判明しました