Rspec Capybara_webkitを使ってjavascriptをテストする
Goal
ゴールと言うか目標はrspecのrequest(integration) testでjavascriptのテストをしたいです。が、いろいろハマってその問題と解決策を時間軸でメモしておきます。
Capybaraについてはある程度知ってる前提です。
javascriptのテストを書く
:js => true
でrspecのintegration testでjavascriptを有効に設定できます。
例:
# in your view erb file | |
<%= link_to_function "test js", '$(this).html("js works")' %> | |
# in test spec | |
it "supports js", :js => true do | |
visit tasks_path | |
click_link "test js" | |
page.should have_content("js works") | |
end |
ただデフォルトではjavascriptをサポートしないので、このspecは失敗します。解決の鍵はcapybara driverというものです。
capybara_webkit driver
なぜcapybara_webkit driver使う
Capybara ... currently comes with Rack::Test and Selenium support built in.
By default, Capybara uses the :rack_test driver, which is fast but does not support JavaScript. You can set up a different default driver for your features.
The capybara-webkit driver is for true headless testing. It uses QtWebKit to start a rendering engine process. It can execute JavaScript as well. It is significantly faster than drivers like Selenium since it does not load an entire browser.
のようにcapybaraは Rack::Test
とSelenium
のdriverがbuilt-inされて、デフォルトdriverは前者の:rack_testでjavascriptをサポートしないです。Seleniumはサポートしますが、それよりも速いのがcapybara-webkit
なのでそれを採用しました。
capybara_webkit driverをインストール
Gemfileにcapybara_webkitを追記、bundle installします。webkitはQTが必要なので、もしそれがないとbundle installで失敗(エラー)します。後はspec_helper.rbにdefault driverをwebkitに設定します。
# webkit-dependency | |
# if you don't have homebrew installed | |
/usr/bin/ruby -e "$(curl -fsSL https://raw.github.com/gist/323731)" | |
# if you don't have QT installed | |
brew install qt | |
# Gemfile, add capybara-webkit | |
group :test, :development do | |
... | |
gem "capybara-webkit" | |
end | |
# in Terminal | |
bundle install | |
# set default capybara driver to webkit. | |
# I put this into spec_helper.rb | |
Capybara.javascript_driver = :webkit | |
# In RSpec, use the :js => true flag | |
it "supports js", :js => true do | |
... | |
end |
これで最初のサンプルspecは通るはずです。
データベースと絡んだテスト
上記のままだとデータベースと絡んだテストはまた失敗します。
例:
it "displays tasks", :js => true do | |
Task.create!(:name => "foo") | |
visit tasks_path | |
click_link 'some link' | |
page.should have_content("some text") | |
end |
自分で確認してみたら、テスト時に作成したデータはjavascriptのテストで使えないっぽいです。Railscastsの記事によりますとspecのテストではデータベーストランザクションを使うが、それがselenium或いはwebkitでは使えないそうです。そのためにdatabase_cleaner
というgemを使います。
database_cleanerを使う
# in Gemfiile | |
group :test, :development do | |
... | |
gem "database_cleaner" | |
end | |
# in Terminal | |
bundle install | |
# in spec_helper.rb | |
RSpec.configure do |config| | |
# ... | |
config.use_transactional_fixtures = false | |
config.before(:suite) do | |
DatabaseCleaner.strategy = :truncation | |
end | |
config.before(:each) do | |
DatabaseCleaner.start | |
end | |
config.after(:each) do | |
DatabaseCleaner.clean | |
end | |
end |
config.use_transactional_fixtures
をfalseにした時点でもうテスト自体は通るはずですが、データはずっとそのまま残ってしまうんです。database_cleanerは名の通りデータベースをテスト前後で綺麗な状態に保つことができます。
これでもう環境面の設定は完了です!