RSpec x Capybara で画面のテストをしていたんだが、JavaScript を叩いてページ遷移している箇所があり、こいつのテストをするのに手間取ってしまった。曰く、
- Capybara-Webkit を使えば JavaScript を絡めた小粋なテストができる
- Qt なるものをインストールしないと Capybara-Webkit はコンパイルできないらしい。
- Xvfb が無いと Capybara-Webkit はwebkit_server を立ちあげられないらしい(こいつを調べるのにくっそ時間がかかった)
まだ完全には理解できていないがひとまず動くようになったので何をやったかをメモしておく。
環境
- OS
Ubuntu 14.04LTS
-
vagrant
のubuntu-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
やったこと順
- capybara-webkit をインストール
Gemfile
group :test do
# ...
gem "capybara-webkit"
# ...
end
$ bundle install --path vendor/bundle --without=production --binstubs=bundle_bin
- 失敗。よくよく README を見ると qt をインストールしろと書いてある
- qt インストール。
$ 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_port
はdiscover_port
から呼び出されており、 -
discover_port
はstart_server
から呼びだされている。 -
start_server
では、はじめにopen_pipe
が呼び出され、SERVER_PATH
をOpen3.popen3
とやらでオープンしようとしている。 - どうもこいつが何かのオープンに失敗しており、
@pipe_stdout.first
がnil
を返すために、文字列判定 に失敗してエラーが投げられる模様 -
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
を叩くだけでテストが動く。