2011年11月 6日 #ruby #rails #rspec #capybara #webkit

Goal

ゴールと言うか目標はrspecのrequest(integration) testでjavascriptのテストをしたいです。が、いろいろハマってその問題と解決策を時間軸でメモしておきます。

Capybaraについてはある程度知ってる前提です。

javascriptのテストを書く

:js => trueでrspecのintegration testでjavascriptを有効に設定できます。
例:

ただデフォルトでは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::TestSeleniumの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に設定します。

これで最初のサンプルspecは通るはずです。

データベースと絡んだテスト

上記のままだとデータベースと絡んだテストはまた失敗します。
例:

自分で確認してみたら、テスト時に作成したデータはjavascriptのテストで使えないっぽいです。Railscastsの記事によりますとspecのテストではデータベーストランザクションを使うが、それがselenium或いはwebkitでは使えないそうです。そのためにdatabase_cleanerというgemを使います。

database_cleanerを使う

config.use_transactional_fixturesをfalseにした時点でもうテスト自体は通るはずですが、データはずっとそのまま残ってしまうんです。database_cleanerは名の通りデータベースをテスト前後で綺麗な状態に保つことができます。

これでもう環境面の設定は完了です!

Resources

日本語

shared_context はその名前の通りコンテキスト (テストを行なうときの状況) を共有するための機能です。
shared_context を使うことで複数箇所にちらばる同一処理をまとめることができます。shared_context は shared_context が書かれたファイルを require することでも使えるようになるので別のスペックファイルでも使うことができます。