Capybaraを使う際に知っておきたいこと

基本的な設定方法や使用方法は書いていません。[CapybaraのREADME](https://github.com/jnicklas/capybara/blob/master/README.md)を読みましょう。

## Driverはどれ使えばいいのか

(参照: [READMEs Drivers section](https://github.com/jnicklas/capybara/blob/5d99d97775015cd5add209837307782f84a7a2a2/README.md#drivers))

種類としては以下の3種類のDriverがあります

|               Driver名               | JSが実行出来るか | 外部HTTP通信が出来るか | headlessかどうか |
|:------------------------------------:|:----------------:|:----------------------:|:----------------:|
|     RackTest                         |        N         |            N           |        Y         |
|     Selenium                         |        Y         |            Y           |        N         |
|     Capybara-webkit, Poltergeist     |        Y         |            Y           |        Y         |

### defaultは?

defaultではRackTestが使用されていて、高速だしRubyで書かれているのでRuby以外に依存してるソフトウェアが無くて良いのですが、JSが実行出来ませんし外部APIとかも叩けません。

個人的な意見としてはJS実行、外部APIを叩くことが必要でなければRackTestのままでいいと思います。

### JS実行や外部APIを叩きたければ?

こうなるとheadlessではないSelenuimか、headless driverであるCapybara-webkitやPoltergeistになってきます。

まず、headlessではないdriverを選んでしまうとテスト実行毎にブラウザが立ち上がってしまいます。これは鬱陶しいのでメインで使うには不適当です。

ということでheadless driverであるCapybara-webkitやPoltergeistになってきます。
最近までは[Capybara-webkit](https://github.com/thoughtbot/capybara-webkit)を使うのが多かった気がするのですが、最近は[Poltergeist](https://github.com/jonleighton/poltergeist)を採用するケースが多い気がします。

理由としては、GitHubの社員が自社内で使用してると思われるRailsアプリの[PR](https://github.com/github/swordfish/pull/32)の中で言ってる通り、

- QT, xvfbに依存していない
- 安定している
- 開発がより盛ん
- より速い

特にQTに依存していないというのは個人的に大きいと思っていて、これのお陰でCI上での実行のしやすがあがりますし、
QTをコンパイルする時間がなくなるのでビルド全体の時間も短縮されます。

下で説明しますがheadlessなのにinspectorも起動出来たり、機能も豊富なのも良いですね。

## デバッグのやりかた

ここからは基本的にPoltergeist driverを使用してること前提に話します。

僕が今までcapybaraのテストを書いていて困った事は主に2つあって、

1. 動作の書き方がわからない（e.x. どういうコードを書いたら特定のボタンが押せるのか
2. テスト上で実行した時だけ機能の挙動が違う

でした、1.は基本的にググって実際に書いてみてやり方を見つけるしかないです。

2.は厄介でして、これは基本的にテスト環境だと違う値のもの(定数だったり設定の値)が影響を及ぼして結果的に違う挙動を引き起こしてることが多いです。

どの値のものが影響を与えてるかは、挙動元のコードを辿ってみていくしか無い気がします。
たどっていう過程で以下の欲求が出てくると思います、それぞれ方法を説明します。

- ある状態での画面の状態を知りたい
- JS側のデバッグをしたい

### ある状態での画面の状態が知りたい

headless driverを使用しているのでボタンを押した後状態とかテストを実行してるだけでは中々分かりにくいです

例えば以下の様なテストがあったとして

```ruby
describe 'Sign up feature' do
  it 'works' do
    visit root_path
    click_on 'Sign up'
    click_on 'hoge'
  end
end
```

よく起こるのが

- "Sign up"押したら、
- root_pathから新規登録ページに飛んで、
- 新規登録ページにある"hoge"をクリックしたいのに、
- "hoge"が見つかりませんとエラーが出る

みたいなケースです。headless driverを使ってるのでSign upをクリックしたあと起こってることが分かりにくいです。

そんな時は以下のようにしてスクリーンショットを撮りましょう

```ruby
 …
    visit root_path
    click_on 'Sign up'
    page.save_screenshot('/path/to/file.png')
    click_on 'hoge'
  end
end
```

`page.save_screenshot`の説明は[ここ](https://github.com/jonleighton/poltergeist#taking-screenshots-with-some-extensions)。

### JS側のデバッグをしたい

サーバー側のデバッグは普通に[pry](https://github.com/pry/pry)を使用した`binding.pry`等でデバッグが可能なのですが、JSはそうにもいきません。

ただJS側でデバッグしたいことは起こるのでそういう時はPoltergeistが提供している[Remote debugging機能](https://github.com/jonleighton/poltergeist#remote-debugging-experimental)を使用します。

この機能を使うには、先ほどのリンクにも記載されてる通り、driverを設定する際、

```ruby
Capybara.register_driver :poltergeist do |app|
  Capybara::Poltergeist::Driver.new(app)
end
```

を

```ruby
Capybara.register_driver :poltergeist do |app|
  Capybara::Poltergeist::Driver.new(app, inspector: true)
end
```

に変えるだけで出来ます。

これによって、例えば先ほどのテストで、以下のように書けば

```ruby
describe 'Sign up feature' do
  it 'works' do
    visit root_path
    page.driver.debug
    click_on 'Sign up'
    click_on 'hoge'
  end
end
```

`page.driver.debug`の時点で以下のようにwebkit inspectorが起動し、"Elements"でhtml DOMを確認したり、"Console"でJSを実行したり出来ます。

![スクリーンショット 2013-10-09 16.31.17.png](https://qiita-image-store.s3.amazonaws.com/0/4163/6b8f2feb-ff02-2b16-14ac-7d921830c10d.png "スクリーンショット 2013-10-09 16.31.17.png")

普段ブラウザ上で行ってるデバッグが可能になります、headless browserなのに :)