元は Rails 2.0.2 と RSpec1.1.3 だったので、今現在最新の Rails 3.2.3 と RSpec 2.10.1 でやってみた
(ruby 1.9.3p194)
New Project
$ rails new myblog : $ cd myblog $ ls Gemfile app/ doc/ script/ Gemfile.lock config/ lib/ test/ README.rdoc config.ru log/ tmp/ Rakefile db/ public/ vendor/
Gemfile
add
gem "rspec-rails", :group => [:development, :test]
bundle install
$bundle install : Using rspec-core (2.10.1) Using rspec-expectations (2.10.0) Using rspec-mocks (2.10.1) Using rspec (2.10.0) Using rspec-rails (2.10.1) :
rspec:install
$ rails generate rspec:install create .rspec create spec create spec/spec_helper.rb
Make test model
$ rails generate model Blog name:string invoke active_record create db/migrate/20120526005010_create_blogs.rb create app/models/blog.rb invoke rspec create spec/models/blog_spec.rb $ rake db:migrate
Make fixtures
$ mkdir spec/fixtures
make file
- spec/fixtures/blogs.yml
one: id: 1 name: 今日の出来事その1 two: id: 2 name: 今日の出来事その2
define the spec
-*- coding: utf-8 -*- require 'spec_helper' describe Blog, "#name が設定されていない場合:" do # pending "add some examples to (or delete) #{__FILE__}" before(:each) do @blog = Blog.new end it "バリデーションに失敗すること" do @blog.should_not be_valid end end
config: .rspec
--colour --format d
Option
- --colour
- 出力に色付ける(default)
- --format
- p はドット
- d はドキュメンテーション
- --profile
- 時間のかかったテストを終了時に表示
run "rake spec SPEC=spec/models/blog_spec.rb"
when failure
$ rake spec SPEC=spec/models/blog_spec.rb /Users/username/.rvm/rubies/ruby-1.9.3-p194/bin/ruby -S rspec spec/models/blog_spec.rb Blog#name が設定されていない場合: バリデーションに失敗すること (FAILED - 1) Failures: 1) Blog#name が設定されていない場合: バリデーションに失敗すること Failure/Error: @blog.should_not be_valid expected valid? to return false, got true # ./spec/models/blog_spec.rb:11:in `block (2 levels) in <top (required)>' Finished in 0.02428 seconds 1 example, 1 failure Failed examples: rspec ./spec/models/blog_spec.rb:10 # Blog#name が設定されていない場合: バリデーションに失敗すること rake aborted! /Users/username/.rvm/rubies/ruby-1.9.3-p194/bin/ruby -S rspec spec/models/blog_spec.rb failed Tasks: TOP => spec (See full trace by running task with --trace)
fix "app/models/blog.rb"
テストに成功するように修正(モデルにバリデーション追加)
class Blog < ActiveRecord::Base attr_accessible :name validates :name, presence: true end
when success
$ rake spec SPEC=spec/models/blog_spec.rb /Users/username/.rvm/rubies/ruby-1.9.3-p194/bin/ruby -S rspec spec/models/blog_spec.rb Blog#name が設定されていない場合: バリデーションに失敗すること Finished in 0.02955 seconds 1 example, 0 failures
edig "app/model/blog_spec.rb"
"#name が設定されていない場合:"
describe Blog, "#name が設定されていない場合:" do : it ":name にエラーが設定されていること" do @blog.should have(1).errors_on(:name) end end
Check
$ rake spec SPEC=spec/models/blog_spec.rb /Users/username/.rvm/rubies/ruby-1.9.3-p194/bin/ruby -S rspec spec/models/blog_spec.rb Blog#name が設定されていない場合: バリデーションに失敗すること :name にエラーが設定されていること Blog は複数の記事を所有できること Finished in 0.21581 seconds 3 examples, 0 failures
「Blog に Entry を追加できること」をスペックとして定義
edit "spec/models/blog_spec.rb"
describe Blog, "に記事を投稿できた場合:" do fixtures :blogs, :entries before do @blog = blogs(:one) end it "記事の件数が1件増えること" do lambda { @blog.entries.create( :title => 'new_post', :body => 'hello', :posted_on => Date.today) }.should change(Entry, :count).by(1) end end
Check
$ rake spec SPEC=spec/models/blog_spec.rb /Users/username/.rvm/rubies/ruby-1.9.3-p194/bin/ruby -S rspec spec/models/blog_spec.rb Blog#name が設定されていない場合: バリデーションに失敗すること :name にエラーが設定されていること Blog は複数の記事を所有できること Blog に記事を投稿できた場合: 記事の件数が1件増えること Finished in 0.27299 seconds 4 examples, 0 failures
model "Entry"
$ rails generate model entry title:string body:text posted_on:date created_at:timestamp updated_at:timestamp blog_id:integer invoke active_record create db/migrate/20120526023402_create_entries.rb create app/models/entry.rb invoke rspec create spec/models/entry_spec.rb rake db:migrate
Make fixtures
- 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
spec/models/entry_spec.rb
# -*- coding: utf-8 -*- require 'spec_helper' describe Entry do # pending "add some examples to (or delete) #{__FILE__}" fixtures :entries, :blogs before(:each) do @entry = entries(:earliest) end it "は特定のブログに属すること" do @entry.blog.should == blogs(:one) end end
run "rake spec SPEC=spec/models/entry_spec.rb"
$ rake spec SPEC=spec/models/entry_spec.rb /Users/username/.rvm/rubies/ruby-1.9.3-p194/bin/ruby -S rspec spec/models/entry_spec.rb Entry は特定のブログに属すること (FAILED - 1) Failures: 1) Entry は特定のブログに属すること Failure/Error: @entry.blog.should == blogs(:one) NoMethodError: undefined method `blog' for #<Entry:0x007f92aca85d68> # ./spec/models/entry_spec.rb:13:in `block (2 levels) in <top (required)>' Finished in 0.18317 seconds 1 example, 1 failure Failed examples: rspec ./spec/models/entry_spec.rb:12 # Entry は特定のブログに属すること rake aborted! /Users/username/.rvm/rubies/ruby-1.9.3-p194/bin/ruby -S rspec spec/models/entry_spec.rb failed Tasks: TOP => spec (See full trace by running task with --trace)
fix
- app/models/entry.rb
class Entry < ActiveRecord::Base attr_accessible :blog_id, :body, :created_at, :posted_on, :title, :updated_at belongs_to :blog end
edit "spec/models/blog_spec.rb"
add
: describe Blog do fixtures :blogs, :entries before do @blog = blogs(:one) end it "は複数の記事を所有できること" do @blog.should have_at_least(2).entries end
Run "rake spec SPEC=spec/models/blog_spec.rb"
$ rake spec SPEC=spec/models/blog_spec.rb /Users/username/.rvm/rubies/ruby-1.9.3-p194/bin/ruby -S rspec spec/models/blog_spec.rb Blog#name が設定されていない場合: バリデーションに失敗すること Blog は複数の記事を所有できること (FAILED - 1) Failures: 1) Blog は複数の記事を所有できること Failure/Error: @blog.should have_at_least(2).entries NoMethodError: undefined method `entries' for #<Blog:0x007fca94f87328> # ./spec/models/blog_spec.rb:26:in `block (2 levels) in <top (required)>' Finished in 0.20175 seconds 2 examples, 1 failure Failed examples: rspec ./spec/models/blog_spec.rb:25 # Blog は複数の記事を所有できること rake aborted! /Users/username/.rvm/rubies/ruby-1.9.3-p194/bin/ruby -S rspec spec/models/blog_spec.rb failed Tasks: TOP => spec (See full trace by running task with --trace)
fix "app/models/blog.rb"
add
has_many :entries
Check
$ rake spec SPEC=spec/models/blog_spec.rb /Users/username/.rvm/rubies/ruby-1.9.3-p194/bin/ruby -S rspec spec/models/blog_spec.rb Blog#name が設定されていない場合: バリデーションに失敗すること Blog は複数の記事を所有できること Finished in 0.32601 seconds 2 examples, 0 failures
define the spec
「Blog に Entry を追加できること」
- spec/models/blog_spec.rb
: describe Blog, "に記事を投稿できた場合:" do fixtures :blogs, :entries before do @blog = blogs(:one) end it "記事の件数が1件増えること" do lambda { @blog.entries.create( :title => 'new_post', :body => 'hello', :posted_on => Date.today) }.should change(Entry, :count).by(1) end end
Run
$ rake spec SPEC=spec/models/blog_spec.rb /Users/username/.rvm/rubies/ruby-1.9.3-p194/bin/ruby -S rspec spec/models/blog_spec.rb Blog#name が設定されていない場合: バリデーションに失敗すること Blog は複数の記事を所有できること Blog に記事を投稿できた場合: 記事の件数が1件増えること Finished in 0.27593 seconds 3 examples, 0 failures
define the spec
記事の投稿日に期待する振舞を定義する
- spec/models/entry_spec.rb
: describe Entry, "#posted_on が入力されずに保存された場合:" do fixtures :blogs before do @entry = Entry.new(:blog_id => blogs(:one), :title => "タイトル", :body => "本文") @entry.save! @entry.reload end it "Entry の作成日は投稿日であること" do @entry.posted_on.should == Date.today end end :
edit app/models/entry.rb
add
before_save :posted_on_today def posted_on_today self.posted_on = Date.today end
Check "rake spec SPEC=spec/models/entry_spec.rb"
$ rake spec SPEC=spec/models/entry_spec.rb /Users/username/.rvm/rubies/ruby-1.9.3-p194/bin/ruby -S rspec spec/models/entry_spec.rb Entry は特定のブログに属すること Entry#posted_on が入力されずに保存された場合: Entry の作成日は投稿日であること Finished in 0.21315 seconds 2 examples, 0 failures
define the spec
"#posted_on を明示して保存された場合:"
describe Entry, "#posted_on を明示して保存された場合:" do fixtures :blogs before do @posted_on = Date.today - 10 @entry = Entry.new(:blog_id => blogs(:one), :title => "タイトル", :body => "本文", :posted_on => @posted_on) @entry.save! @entry.reload end it "入力された日付が投稿日であること" do @entry.posted_on.should == @posted_on end end
edit app/models/entry.rb
fix
# self.posted_on = Date.today self.posted_on ||= Date.today
Check
$ rake spec SPEC=spec/models/entry_spec.rb /Users/username/.rvm/rubies/ruby-1.9.3-p194/bin/ruby -S rspec spec/models/entry_spec.rb Entry は特定のブログに属すること Entry#posted_on が入力されずに保存された場合: Entry の作成日は投稿日であること Entry#posted_on を明示して保存された場合: 入力された日付が投稿日であること Finished in 0.26126 seconds 3 examples, 0 failures
check all
$ rake spec /Users/username/.rvm/rubies/ruby-1.9.3-p194/bin/ruby -S rspec ./spec/models/blog_spec.rb ./spec/models/entry_spec.rb Blog#name が設定されていない場合: バリデーションに失敗すること :name にエラーが設定されていること Blog は複数の記事を所有できること Blog に記事を投稿できた場合: 記事の件数が1件増えること Entry は特定のブログに属すること Entry#posted_on が入力されずに保存された場合: Entry の作成日は投稿日であること Entry#posted_on を明示して保存された場合: 入力された日付が投稿日であること Finished in 0.65501 seconds 7 examples, 0 failures
*1:修正: 20120527