RSpec Capybara Webkit Xvfb CentOS 要するにRailsでjavascriptをテストしたい

RSpec + Capybara のセットアップは簡単でいいんですが、javascriptのテストができません。
いざ本当にウェブサイトやウェブアプリのテストしようと思ったらjavascriptのテストは必須。
それを可能にするには意外にも長い道のりがあるので、まとめておきます。

想定する開発環境はこんな感じ。

macbook dev environment

テストについてよくわからなければ、このチュートリアルで学習。
Ruby on Rails チュートリアル:実例を使って Rails を学ぼう

テスト駆動開発の定義とは、アプリケーションを開発するときに最初にテストを作成し、次にコードを作成することです。この開発手法に慣れるまでには多少時間がかかるかもしれませんが、一度慣れてしまえば大きなメリットを得られます。失敗するテストを最初に書き、テストにパスするコードを次に実装することで、しかるべき振る舞いがテストによって正しく検証されている、という自信が付きます。
  • スタート地点 • Rails4でアプリ書いてて、テストもしてるけど、javascriptを交えたテストはまだしていない。 • Capybaraではjavascriptが動作しないのでテストに失敗する。

道のり

  • javascriptのテストには describe に js: true オプションをつければよい
  • その際使われるデフォルトの javascript_driver は selenium
  • javascript_driver を capybara-webkit に変更することもできる
    -- CentOS に QT をインストールする必要がある

  • selenium にしろ webkit にしろ、仮想サーバーでテストするのでディスプレイがない( headless )
    -- ディスプレイ処理を可能にする X が必要
    -- X を仮想的に実現する Xvfb ( virtual framebuffer X server )
    -- Xvfb を ruby から簡単に立ち上げられる headless という Gem がある

  • js: true を付けられたテストは、別スレッドでRailsアプリケーションを起動しテストする
    -- そのためデータベースが各テストで共有されず、エラーになる
    --- config.use_transactional_fixtures は使わない
    --- database_cleaner を使って毎回データベースを掃除する

  • spec_helper.rb をもろもろ変更する

Xvfb

インストール

1
2
3
4
5
6
7
$ yum search Xvfb
===== N/S Matched: Xvfb =====
xorg-x11-server-Xvfb.x86_64 : A X Windows System virtual framebuffer X server.

$ sudo yum groupupdate "X Window System"

$ sudo yum install xorg-x11-server-Xvfb

確認

1
2
3
ディスプレイ番号を環境変数に設定。
$ DISPLAY=:1.0
$ export DISPLAY

Xvfbをディスプレイ番号:1、スクリーン番号:0、幅:1024px、高さ:768px、ビット深度:24bit で起動。

1
2
3
4
5
6
7
8
コマンドの最後に&を付加することにより、バックグラウンドで動かすことができる。
$ Xvfb :1 -screen 0 1024x768x24&

実行中のジョブを表示するには下記.
$ jobs

終了する
$ killall Xvfb

テストとは直接関係ないけど xwd と ImageMagick をインストールしたらスクリーンショットも撮れる。

1
2
3
4
5
6
7
8
9
10
$ yum install ImageMagick
$ yum install xwd

$ xwd -display :1 -root -out test.xwd
-display ディスプレイ番号
-root    ディスプレイ全体を撮る
-out     出力ファイル名

ImageMagickのconvertコマンドでpngに変換。
$ convert test.xwd test.png

Gem

必要なGemをインストールする。

1
2
3
4
5
6
7
8
group :test do
  gem 'selenium-webdriver', '~> 2.35.1' # javascript_driver
  gem 'capybara', :git => 'git://github.com/jnicklas/capybara.git'
  gem 'factory_girl_rails', '4.2.1'
  gem 'database_cleaner' # データベースが絡むテストには必要
  # gem 'capybara-webkit' # デフォルトのjavascript_driverを変更する場合
  gem 'headless' # Railsから簡単にXvfbを起動できる
end

capybara-webkitのインストールにはQTが必要。
※ ページ下部を参照。

1
$ bundle install

spec_helper.rb

spec_helper.rbにいろいろ設定する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  .
  .
  require 'rspec/rails'
  require 'rspec/autorun'
  require 'capybara/rspec'
  require 'capybara-webkit'
  require 'headless'
  require 'database_cleaner'

  RSpec.configure do |config|
    Capybara.javascript_driver = :selenium
    # もしくは、Capybara.javascript_driver = :webkit

    config.before(:suite) do
      # Xvfbを起動するheadlessの設定
      Headless.new(:destroy_on_exit => false).start
    end

    # javascriptテストとスレッドを共有するにはfalseにする
    config.use_transactional_fixtures = false
  .
  .
  end

database_cleaner

spec/support/に database_cleaner.rb というファイルを作成
※ ファイル名はお好みで

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
RSpec.configure do |config|

  # 処理が高速なので、普段はtransactionを使用する
  config.before(:each) do
    DatabaseCleaner.strategy = :transaction
  end

  # jsオプションが有効な時のテストはtruncationを使用
  config.before(:each, :js => true) do
    DatabaseCleaner.strategy = :truncation
  end

  # database cleaner の設定

  config.before(:suite) do
    DatabaseCleaner.clean_with(:truncation)
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end

end

capybara-webkit

javascript_driverをcapybara-webkitすると処理が高速になりました。
javascriptほとんど使っていないテストですけど、結構違う。

selenium: Finished in 1 minute 31.15 seconds
webkit: Finished in 1 minute 11.55 seconds

capybara-webkitのインストールにはQTが必要。
CentOS 6.4の場合は以下の手順。

/etc/yum.repos.d/ にファイル作成

1
$ sudo vi /etc/yum.repos.d/qt.repo

下記をコピペ、保存。

1
2
3
4
5
6
7
8
9
10
11
12
13
[epel-qt48]
name=Software Collection for Qt 4.8
baseurl=http://repos.fedorapeople.org/repos/sic/qt48/epel-$releasever/$basearch/
enabled=1
skip_if_unavailable=1
gpgcheck=0

[epel-qt48-source]
name=Software Collection for Qt 4.8 - Source
baseurl=http://repos.fedorapeople.org/repos/sic/qt48/epel-$releasever/SRPMS
enabled=0
skip_if_unavailable=1
gpgcheck=0
1
2
3
4
5
6
7
8
インストール
yum install qt48-qt-webkit-devel
シンボリックリンク
ln -s /opt/rh/qt48/root/usr/include/QtCore/qconfig-64.h  /opt/rh/qt48/root/usr/include/QtCore/qconfig-x86_64.h
実行
source /opt/rh/qt48/enable

export PATH=/opt/rh/qt48/root/usr/lib64/qt4/bin/${PATH:+:${PATH}}

その他のOS、バージョンは下記参照。
Installing Qt and compiling capybara webkit · thoughtbot/capybara-webkit Wiki · GitHub

テスト

テストの記述自体はこんな感じ。
js: true オプションを忘れずに。

1
2
3
4
5
6
7
describe "User page", js: true do
 before do
   sign_in user
   visit user_path(user)
 end
 it { should have_content('User profile') }
end

以上です。
いろいろとやることがありますが、
一度セットアップするだけなので、頑張りましょー。

参考

thoughtbot/capybara-webkit · GitHub

bmabey/database_cleaner · GitHub

Headless, a Ruby wrapper for Xvfb – gem, headless, Ruby, rubygems, Xvfb – Leonid Shevtsov

Configuring database_cleaner with Rails, RSpec, Capybara, and Selenium | Virtuous Code

RSpecとCapybaraでJavaScript/Ajaxをテストする - Rails 雑感 - Ruby on Rails with OIAX

#gemfile rails 3, rspec-rails, capybara, capybara-webkit, headless in order to run request specs that can test javascript

何かありましたらコメントをどうぞ

comments powered by Disqus

人気の記事

950 Points チリ出身のギタリストが弾くドラゴンボールZがむちゃくちゃかっこいい…
774 Points Wordpress + Heroku + PostgreSQL + Amazon S3 = ¥0 / 無料でサイト運営
700 Points Rubyのチートシート 変数 / クラス / モジュール
524 Points Rubyのチートシート / アクティブサポート
451 Points 紙のデザイナーがウェブ開発できるようになるまでに必要なこと
435 Points Rails / Google Analyticsのデータを使って分析や管理画面のためのグラフをつくる
323 Points RailsとHerokuでノーティフィケーションをプッシュする / PusherとTurbolinksの兼ね合い
222 Points Rails / RSpec テスト書いたことない メンドクサイ(n´Д`)という時のチートシート
193 Points Rails / Ajaxを使って画面遷移しない一時保存機能をつける
193 Points Protractorでスクレイピングしてみた