Help us understand the problem. What is going on with this article?

これからテストを書き始めたい人のための 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へ続きます。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away