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: ひづ・ふぃなーれ!
ここから本編
おまたせしました。いよいよテストコードと、それに通るコードを書いていきます。
それでは実行してみる
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
無事にグリーンになりました。今日はこれまで!