RSpec x Capybara x Webkit x X Server で JavaScript の絡むテストの自動化

  • 6
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

RSpec x Capybara で画面のテストをしていたんだが、JavaScript を叩いてページ遷移している箇所があり、こいつのテストをするのに手間取ってしまった。曰く、

  • Capybara-Webkit を使えば JavaScript を絡めた小粋なテストができる
  • Qt なるものをインストールしないと Capybara-Webkit はコンパイルできないらしい。
  • Xvfb が無いと Capybara-Webkit はwebkit_server を立ちあげられないらしい(こいつを調べるのにくっそ時間がかかった)

まだ完全には理解できていないがひとまず動くようになったので何をやったかをメモしておく。

環境

  • OS
    • Ubuntu 14.04LTS
    • vagrantubuntu-14.04-amd64 という box を使っている。
  • Ruby
    • 2.2.3
  • Rails
    • 4.2.4
  • RSpec
    • 3.3.0
  • Capybara
    • 2.5.0
  • Capybara-Webkit
    • 1.7.1
  • qmake
    • 4.8.6
    • テストを走らせると WARNING: The next major version of capybara-webkit will require at least version 5.0 of Qt. You're using version 4.8.6. と出るんだが qt5 のインストール方法は未調査
  • xvfb
    • 2:1.15.1-0ubuntu2.7

やったこと順

Gemfile
group :test do
  # ...
  gem "capybara-webkit"
  # ...
end
$ bundle install --path vendor/bundle --without=production --binstubs=bundle_bin
$ sudo apt-get install -y libqtwebkit-dev qt4-qmake
  • 再び bundle インストール。今度はうまくいく
  • テスト実行
$ rspec
...
Capybara::Webkit::ConnectionError:
... capybara-webkit-1.7.1/bin/webkit_server failed to start.
  • 失敗。ググっても大した情報は得られず。
  • 仕方ないのでソースを読む
  • ConnectionError を出しているのはどうやらここ
  • parse_portdiscover_port から呼び出されており、
  • discover_portstart_server から呼びだされている。
  • start_server では、はじめに open_pipe が呼び出され、 SERVER_PATHOpen3.popen3 とやらでオープンしようとしている。
  • どうもこいつが何かのオープンに失敗しており、@pipe_stdout.firstnil を返すために、文字列判定 に失敗してエラーが投げられる模様
  • SERVER_PATH が指す webkit_server というのが実行可能なファイルのようなので、実行してみる。すると以下のエラーが。
$ vendor/bundle/ruby/2.2.0/gems/capybara-webkit-1.7.1/bin/webkit_server
webkit_server: cannot connect to X server
  • エラーでググッてここにたどり着く。
  • あー xvfb てのが必要なのねってことでインストール
$ sudo apt-get install -y xvfb
  • インストール後下記を実行
$ Xvfb :1 -screen 0 1024x768x16 -nolisten inet6
  • すると、X Server が立ち上がり臨戦態勢に。こいつにプロセス奪われてたんじゃテストできないじゃん
  • 仕方ないので別タブで開発サーバーに入り、そっちで起動する。
  • テスト用タブでは下記を実行し、テスト
$ export DISPLAY=localhost:1.0
$ rspec
  • これでようやく動く

まとめると

  • xvfb インストール
$ sudo apt-get install -y xvfb

  • qt インストール
$ sudo apt-get install -y libqtwebkit-dev qt4-qmake
  • capybara-webkit インストール
Gemfile
group :test do
  # ...
  gem "capybara-webkit"
  # ...
end
$ bundle install --path vendor/bundle --without=production --binstubs=bundle_bin
  • xvfb 起動
$ Xvfb :1 -screen 0 1024x768x16 -nolisten inet6
  • DISPLAY を指定してからテスト実行
$ export DISPLAY=localhost:1.0
$ rspec

自動化

rspec 使うたび、あるいは開発環境起動するたびに Xvfbも立ち上げるのは面倒くさいので自動化したい。そこで、テストのはじめに別プロセスで立ち上げ、テストの終わりに killall で葬り去ることにした。

spec/rails-helper.rb に下記の通り追記

spec/rails-helper.rb
config.before :suite do
  system "Xvfb :1 -screen 0 1024x768x16 -nolisten inet6 &"
end

config.after :suite do
  system "killall Xvfb"
end

環境変数 DISPLAY は、.env ファイルに追記(多分 dotenv という gem が必要)

.env
DISPLAY="localhost:1.0"

これで、 RSpec を叩くだけでテストが動く。