Rails
RSpec
Spork
FactoryGirl

これからテストを書き始めたい人のための Rails+RSpec+Spork+FactoryGirl チュートリアル(その1)

More than 5 years have passed since last update.

「今まで Rails でテストを疎かにしてきたけど、これからはちゃんとテストを書きたいな」と思っている人のためのチュートリアルです。

(自分用のメモでもあります。。)


環境


  • Mac OS X 10.6.8

  • Ruby 1.9.2

  • Rails 3.2.6

  • RSpec 2.10.0

  • Spork 0.9.2

  • FactoryGirl 3.4.0

  • DatabaseCleaner 0.8.0

  • MySQL 5.5.15


プロジェクトを生成

チュートリアル用の Rails 3.2 アプリケーションを生成します。

Rails 標準の Test::Unit ではなく、RSpec を使います。

$ rvm 1.9.2-p290@rails32

$ mkdir ~/projects && cd ~/projects
$ rails new blog -T -d mysql --skip-bundle && cd blog
create
create README.rdoc
create Rakefile
create config.ru
create .gitignore
create Gemfile
create app
create app/assets/images/rails.png
create app/assets/javascripts/application.js
create app/assets/stylesheets/application.css
create app/controllers/application_controller.rb
create app/helpers/application_helper.rb
create app/mailers
create app/models
create app/views/layouts/application.html.erb
create app/mailers/.gitkeep
create app/models/.gitkeep
create config
create config/routes.rb
create config/application.rb
create config/environment.rb
create config/environments
create config/environments/development.rb
create config/environments/production.rb
create config/environments/test.rb
create config/initializers
create config/initializers/backtrace_silencers.rb
create config/initializers/inflections.rb
create config/initializers/mime_types.rb
create config/initializers/secret_token.rb
create config/initializers/session_store.rb
create config/initializers/wrap_parameters.rb
create config/locales
create config/locales/en.yml
create config/boot.rb
create config/database.yml
create db
create db/seeds.rb
create doc
create doc/README_FOR_APP
create lib
create lib/tasks
create lib/tasks/.gitkeep
create lib/assets
create lib/assets/.gitkeep
create log
create log/.gitkeep
create public
create public/404.html
create public/422.html
create public/500.html
create public/favicon.ico
create public/index.html
create public/robots.txt
create script
create script/rails
create tmp/cache
create tmp/cache/assets
create vendor/assets/javascripts
create vendor/assets/javascripts/.gitkeep
create vendor/assets/stylesheets
create vendor/assets/stylesheets/.gitkeep
create vendor/plugins
create vendor/plugins/.gitkeep


RSpecを使う

RSpec を使うため、Gemfile に追記します。

$ vim Gemfile


Gemfile

group :development, :test do

gem 'rspec-rails', '2.10.1'
end

gem をインストールします。

$ bundle --path vendor/bundle

Fetching source index for https://rubygems.org/
Installing rake (0.9.2.2)
Installing i18n (0.6.0)
Installing multi_json (1.3.6)
Installing activesupport (3.2.6)
Installing builder (3.0.0)
Installing activemodel (3.2.6)
Installing erubis (2.7.0)
Installing journey (1.0.4)
Installing rack (1.4.1)
Installing rack-cache (1.2)
Installing rack-test (0.6.1)
Installing hike (1.2.1)
Installing tilt (1.3.3)
Installing sprockets (2.1.3)
Installing actionpack (3.2.6)
Installing mime-types (1.18)
Installing polyglot (0.3.3)
Installing treetop (1.4.10)
Installing mail (2.4.4)
Installing actionmailer (3.2.6)
Installing arel (3.0.2)
Installing tzinfo (0.3.33)
Installing activerecord (3.2.6)
Installing activeresource (3.2.6)
Using bundler (1.0.21)
Installing coffee-script-source (1.3.3)
Installing execjs (1.4.0)
Installing coffee-script (2.2.0)
Installing rack-ssl (1.3.2)
Installing json (1.7.3) with native extensions
Installing rdoc (3.12)
Installing thor (0.15.2)
Installing railties (3.2.6)
Installing coffee-rails (3.2.2)
Installing diff-lcs (1.1.3)
Installing jquery-rails (2.0.2)
Installing mysql2 (0.3.11) with native extensions
Installing rails (3.2.6)
Installing rspec-core (2.10.1)
Installing rspec-expectations (2.10.0)
Installing rspec-mocks (2.10.1)
Installing rspec (2.10.0)
Installing rspec-rails (2.10.1)
Installing sass (3.1.19)
Installing sass-rails (3.2.5)
Installing uglifier (1.2.4)
Your bundle is complete! It was installed into ./vendor/bundle

bundle installbundle と省略できます。

また、--path オプションにより gem のインストール先を指定すると、.bundle/config ファイルが生成されます。

---

BUNDLE_PATH: vendor/bundle
BUNDLE_DISABLE_SHARED_GEMS: '1'

BUNDLE_PATH が設定されるため、次回以降 bundle install する際に --path は必要ありません。

次に、RSpec の初期設定を行います。

$ bundle exec rails g rspec:install

create .rspec
create spec
create spec/spec_helper.rb

これで、Rails で RSpec が使えるようになりました。


アプリケーションの雛形を生成

例として、Article モデルを扱うコードを Scaffold で生成します。

$ bundle exec rails g scaffold article title:string content:text

invoke active_record
create db/migrate/20120616114653_create_articles.rb
create app/models/article.rb
invoke rspec
create spec/models/article_spec.rb
invoke resource_route
route resources :articles
invoke scaffold_controller
create app/controllers/articles_controller.rb
invoke erb
create app/views/articles
create app/views/articles/index.html.erb
create app/views/articles/edit.html.erb
create app/views/articles/show.html.erb
create app/views/articles/new.html.erb
create app/views/articles/_form.html.erb
invoke rspec
create spec/controllers/articles_controller_spec.rb
create spec/views/articles/edit.html.erb_spec.rb
create spec/views/articles/index.html.erb_spec.rb
create spec/views/articles/new.html.erb_spec.rb
create spec/views/articles/show.html.erb_spec.rb
invoke helper
create spec/helpers/articles_helper_spec.rb
create spec/routing/articles_routing_spec.rb
invoke rspec
create spec/requests/articles_spec.rb
invoke helper
create app/helpers/articles_helper.rb
invoke rspec
invoke assets
invoke coffee
create app/assets/javascripts/articles.js.coffee
invoke scss
create app/assets/stylesheets/articles.css.scss
invoke scss
create app/assets/stylesheets/scaffolds.css.scss

DB の設定を行います。

$ vim config/database.yml


config/database.yml

common: &common

adapter: mysql2
encoding: utf8
reconnect: false
pool: 5
username: root
password: yourpassword
host: localhost

development:
<<: *common
database: blog_dev

test:
<<: *common
database: blog_test

production:
<<: *common
database: blog


DB およびテーブルを作成します。

$ bundle exec rake db:create

$ bundle exec rake db:migrate
== CreateArticles: migrating =================================================
-- create_table(:articles)
-> 0.0896s
== CreateArticles: migrated (0.0897s) ========================================

これで、アプリケーションが動作するようになりました。


テストを実行

ひとまず、テストを実行してみます。

$ bundle exec rake

下記のコマンドでも実行できます。

$ bundle exec rspec spec

2つのテストが Pending となっていることがわかります。


  • spec/helpers/articles_helper_spec.rb

  • spec/models/article_spec.rb

Pending のテストコードを削除します。

$ vim spec/helpers/articles_helper_spec.rb


spec/helpers/articles_helper_spec.rb

require 'spec_helper'

# Specs in this file have access to a helper object that includes
# the ArticlesHelper. For example:
#
# describe ArticlesHelper do
# describe "string concat" do
# it "concats two strings with spaces" do
# helper.concat_strings("this","that").should == "this that"
# end
# end
# end
describe ArticlesHelper do
# pending "add some examples to (or delete) #{__FILE__}" を削除
end


$ vim spec/models/article_spec.rb


spec/models/article_spec.rb

require 'spec_helper'

describe Article do
# pending "add some examples to (or delete) #{__FILE__}" を削除
end


テストを実行し、すべてのテストが「成功」となっていることを確認します。

$ bundle exec rspec spec

............................

Finished in 0.80978 seconds
28 examples, 0 failures


テストコードを実装

正常にモデルが new されることを検証するテストを書いてみます。

$ vim spec/models/article_spec.rb


spec/models/article_spec.rb

# coding: utf-8

require 'spec_helper'

describe Article do
describe '.new' do
context 'given valid attributes' do
subject { Article.new(:title => 'a', :content => 'a') }
it { should be_valid }
end
end
end


テストを実行して「成功」となっていることを確認します。

$ bundle exec rspec spec

.............................

Finished in 0.69964 seconds
29 examples, 0 failures

ひとつのファイルのみ実行したい場合は、下記のように実行します。

$ bundle exec rspec spec/models/article_spec.rb

.

Finished in 0.09452 seconds
1 example, 0 failures

続いて、Article モデルの title は必須となることを想定してテストを書きます。

$ vim spec/models/article_spec.rb


spec/models/article_spec.rb

# coding: utf-8

require 'spec_helper'

describe Article do
describe '.new' do
context 'given valid attributes' do
subject { Article.new(:title => 'a', :content => 'a') }
it { should be_valid }
end

# 追記ここから
context 'given null title' do
subject { Article.new(:content => 'a') }
it { should have(1).errors_on(:title) }
end
# 追記ここまで
end
end


$ vim spec/controllers/articles_controller_spec.rb


spec/controllers/articles_controller_spec.rb

def valid_attributes

{:title => 'a', :content => 'a'}
end

プロダクトコードを実装していませんが、試しにテストを実行してみます。

$ bundle exec rspec spec

.................F............

Failures:

1) Article.new given null title
Failure/Error: it { should have(1).errors_on(:title) }
expected 1 errors on :title, got 0
# ./spec/models/article_spec.rb:14:in `block (4 levels) in <top (required)>'

Finished in 0.74384 seconds
30 examples, 1 failure

Failed examples:

rspec ./spec/models/article_spec.rb:14 # Article.new given null title

結果は当然「失敗」となります。

それでは、Article モデルにバリデーションを実装します。

$ vim app/models/article.rb


app/models/article.rb

# coding: utf-8

class Article < ActiveRecord::Base
attr_accessible :content, :title

validates(:title, :presence => true)
end


テストを実行します。

$ bundle exec rspec spec

..............................

Finished in 0.87777 seconds
30 examples, 0 failures

バリデーションを実装したため、結果は「成功」となります。

その2へ続きます。