これから始める Ruby on Rails シリーズRuby on Rails:RSpecとCapybaraで初めてのインテグレーションテスト
はじめに
前回の記事では簡単な静的ページを作りました。今回はその静的ページに対して、RSpecを使った簡単なテストを実装してみます。この記事の内容はRuby on Rails チュートリアル第3章の2項 最初のテストを参考にしています。Ruby on Railsおよびrspecを最新版で行っているため、チュートリアルとは異なる部分があります。
RSpecとは
テストについてほとんど知識がないので、RSpecを使ったテストコードを読もう (2/4)を引用してきました。
RSpecとは、Rubyで書かれたプログラムの動作を確認するための、テストコードを記述・実行するためのフレームワークのことです。 実際に動くプログラムの動作のことを振る舞い(ビヘイビア)と呼ぶことから、それまでのテスト駆動開発のやり方をビヘイビア駆動開発(BDD)と呼ぶようになっています。
テスト駆動開発(TDD)はよく耳にしますが、ビヘイビア駆動開発というのは初耳ですね。自分のようにRuby on Railsの勉強と合わせてテストも勉強してみようという方にはこのサイト「Everyday Rails - RSpecによるRailsテスト入門」(電子書籍版あり)もとても役立つ気がしています。この書籍はRSpecに特化した書籍なので、Ruby on Rails チュートリアルで全体像を理解しつつ、必要に応じて読むようにしています。
RSpecと合わせて使うCapybara
Capybaraとはユーザーの操作をエミュレーション(たとえば、ページ遷移)しながらそこにエラーがないかをテストできます。この指定をRSpecを通して自動化できます。
RSpecをインストールする
前回の環境をコピーするかブランチを作りrspecを試す環境を作ります。Gemfileを開き、rspec-rails
とcapybara
を追加します。
group :development, :test do
gem 'rspec-rails'
gem 'capybara'
end
Gemfileへの追記が終わったらbundle install
でインストールします。 Yosemiteにバージョンアップしていて、エラーが出た場合はこの記事の下部を参考にしてください。
インストールされるバージョン
上記Gemfileの指定でインストールされたバージョンは以下の通りです。
capybara (2.4.4)
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (~> 2.0)
rspec-rails (3.1.0)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
rspec-core (~> 3.1.0)
rspec-expectations (~> 3.1.0)
rspec-mocks (~> 3.1.0)
rspec-support (~> 3.1.0)
RSpecを使う準備
インストールが完了したら、RSpecの設定ファイルを作り設定を追記します。$ rails generate rspec:install
というコマンドでspec_helper.rb
とrails_helper.rb
が作られます。
$ rails generate rspec:install
create .rspec
force spec/spec_helper.rb
create spec/rails_helper.rb
spec_helper.rb
はRSpecに関する設定、rails_helper.rb
にはRailsに関する設定を記述します。今回はspec_helper.rb
だけ手を入れます。
spec_helper.rbに設定を追記
実はそのままでは動かすことができません。そのままではuninitialized constant Capybara (NameError)
というエラーが出てしまったため、こちらrspec の実行で “uninitialized constant Capybara (NameError)”を参考に設定を書き加えました。RSpec.configure do |config|
の中に3行追記します。
RSpec.configure do |config|
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
加えて、最後のend
の前にCapybaraに関する指定を1行追記します。
config.include Capybara::DSL
end
インテグレーションテスト(総合テスト)を作る
静的ページstatic_pages
に対して、インテグレーションテストを作ります。
$ rails generate integration_test static_pages
invoke rspec
create spec/requests/static_pages_spec.rb
生成されたspec/requests
ディレクトリのstatic_pages_spec.rb
を開きます。 先頭のrequire 'rails_helper'
はrequire 'spec_helper'
に書き換えます。
英語で記述するとこんな感じ。
require 'spec_helper'
RSpec.describe "StaticPages" do
describe "Home page" do
it "should have the content 'Sample App'" do
visit '/static_pages/home'
expect(page).to have_content('Sample App')
end
end
end
日本語で表してみるとこうなります。
require 'spec_helper'
RSpec.describe "StaticPages コントローラの" do
describe "Home ページに" do
it "文字列'Sample App'が含まれているか" do
visit '/static_pages/home'
expect(page).to have_content('Sample App')
end
end
end
テスト対象となるViewのhome(app/views/static_pages/home.html.erb
)はそのままにしておきます。
<h1>StaticPages#home</h1>
<p>Find me in app/views/static_pages/home.html.erb</p>
テストを実行する
対象のViewには手を加えず、意図的にテストを失敗させます。 $ rspec spec/requests/static_pages_spec.rb
で実際にテストを実行してみます。
$ rspec spec/requests/static_pages_spec.rb
F
Failures:
1) StaticPages コントローラの Home ページに 文字列'Sample App'が含まれているか
Failure/Error: expect(page).to have_content('Sample App!')
expected #has_content?("Sample App") to return true, got false
# ./spec/requests/static_pages_spec.rb:7:in `block (3 levels) in <top (required)>'
Finished in 0.07151 seconds (files took 2.19 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/requests/static_pages_spec.rb:5 # StaticPages コントローラの Home ページに 文字列'Sample App'が含まれているか
失敗したテストが表示されていますね。
テストを成功させる
次にHTML(app/views/static_pages/home.html.erb
)にSample App
を加えて、テストを成功させます。
<h1>Sample App</h1>
<p>Find me in app/views/static_pages/home.html.erb</p>
保存したら、もう一度$ rspec spec/requests/static_pages_spec.rb
を実行します。
$ rspec spec/requests/static_pages_spec.rb
.
Finished in 0.05663 seconds (files took 1.83 seconds to load)
1 example, 0 failures
無事成功しました。これで、テストが動くことを確認できました。
初めてのテストはここまで。Ruby on Railsを読んで続きができたら次回を書きたいと思います。
途中でエラーが出た方は以下を参考にしてみてください。
エラーについて
bundle installで起こるエラー
bundle install時に下記のようなエラーが出たらXcodeのコマンドラインツールが古いかもしれません。$ xcode-select --install
を試してみてください。
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.
/Users/ryuichi/.rbenv/versions/2.1.0/bin/ruby extconf.rb
Building nokogiri using packaged libraries.
-----
libiconv is missing. please visit http://nokogiri.org/tutorials/installing_nokogiri.html for help with installing dependencies.
-----
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers. Check the mkmf.log file for more details. You may
need configuration options.
Provided configuration options:
--with-opt-dir
--without-opt-dir
--with-opt-include
source 'https://rubygems.org'
--without-opt-include=${opt-dir}/include
--with-opt-lib
--without-opt-lib=${opt-dir}/lib
--with-make-prog
--without-make-prog
--srcdir=.
--curdir
--ruby=/Users/ryuichi/.rbenv/versions/2.1.0/bin/ruby
--help
--clean
--use-system-libraries
--enable-static
--disable-static
--with-zlib-dir
--without-zlib-dir
--with-zlib-include
--without-zlib-include=${zlib-dir}/include
--with-zlib-lib
--without-zlib-lib=${zlib-dir}/lib
--enable-cross-build
--disable-cross-build
extconf failed, exit code 1
Gem files will remain installed in /Users/ryuichi/Projects/Labs/step4.rspec.rails/vendor/bundle/ruby/2.1.0/gems/nokogiri-1.6.3.1 for inspection.
Results logged to /Users/ryuichi/Projects/Labs/step4.rspec.rails/vendor/bundle/ruby/2.1.0/extensions/x86_64-darwin-13/2.1.0-static/nokogiri-1.6.3.1/gem_make.out
An error occurred while installing nokogiri (1.6.3.1), and Bundler cannot continue.
Make sure that `gem install nokogiri -v '1.6.3.1'` succeeds before bundling.
bundle install時にNokogiriに関するエラー
このエラーが出たときはエラー内に解決方法が書かれています。$ bundle config build.nokogiri --use-system-libraries
を実行してから$ bundle install
しましょう。
IMPORTANT! Nokogiri builds and uses a packaged version of libxml2.
If this is a concern for you and you want to use the system library
instead, abort this installation process and reinstall nokogiri as
follows:
gem install nokogiri -- --use-system-libraries
If you are using Bundler, tell it to use the option:
bundle config build.nokogiri --use-system-libraries
bundle install
However, note that nokogiri does not necessarily support all versions
of libxml2.
For example, libxml2-2.9.0 and higher are currently known to be broken
and thus unsupported by nokogiri, due to compatibility problems and
XPath optimization bugs.
************************************************************************
Building libxslt-1.1.28 for nokogiri with the following patches applied:
- 0001-Adding-doc-update-related-to-1.1.28.patch
- 0002-Fix-a-couple-of-places-where-f-printf-parameters-wer.patch
- 0003-Initialize-pseudo-random-number-generator-with-curre.patch
- 0004-EXSLT-function-str-replace-is-broken-as-is.patch
- 0006-Fix-str-padding-to-work-with-UTF-8-strings.patch
- 0007-Separate-function-for-predicate-matching-in-patterns.patch
- 0008-Fix-direct-pattern-matching.patch
- 0009-Fix-certain-patterns-with-predicates.patch
- 0010-Fix-handling-of-UTF-8-strings-in-EXSLT-crypto-module.patch
- 0013-Memory-leak-in-xsltCompileIdKeyPattern-error-path.patch
- 0014-Fix-for-bug-436589.patch
- 0015-Fix-mkdir-for-mingw.patch
************************************************************************
IMPORTANT! Nokogiri builds and uses a packaged version of libxslt.
If this is a concern for you and you want to use the system library
instead, abort this installation process and reinstall nokogiri as
follows:
gem install nokogiri -- --use-system-libraries
If you are using Bundler, tell it to use the option:
bundle config build.nokogiri --use-system-libraries
bundle install
************************************************************************
以上、はじめてのテストでした。
シリーズ
- Ruby on Railsの最初の一歩
- Ruby on RailsアプリをHerokuにデプロイしてみる
- $ bundle exec を省略する
- Ruby on Railsで静的ページを作る
- Ruby on Rails:RSpecとCapybaraで初めてのインテグレーションテスト
- Ruby on Rails:埋め込みRubyを使った簡単な動的ページを作る
- Ruby on Rails:Guardを使ったテストの自動化