今回初めて、個人用にクローラーを開発してみました。
JavaScript多めのサイトのため、「Capybara + Poltergeist」を使用しました。
順調に開発は進んだのですが、テストってどう書けばいいんだろうと思い、知り合いに相談したところ、下記方針に決まりました。
- feature_specとして書く
- 毎回アクセスするのはよろしくないので、用意したHTMLファイルを解析する
やり方
CapybaraのHTTPリクエストをstub化する
毎回アクセスしないように、CapybaraのHTTPリクエストをstub化し、用意したローカルのHTMLファイルを返却するようにします。
HTTPリクエストをスタブ化するGemとして「webmock」は有名だと思います。
github.com
しかし、これはCapybaraでは使えません。
代わりに「puffing-billy」を使います。
github.com
Gemをインストールして、設定を追加します。
README通りだと、jsのエラーが無視されずRspecが失敗してしまうため、私は以下のように設定しました。
Capybara.register_driver :pg_billy do |app|
options = {
js_errors: false,
phantomjs_options: [
'--ignore-ssl-errors=yes',
"--proxy=#{Billy.proxy.host}:#{Billy.proxy.port}"
]
}
Capybara::Poltergeist::Driver.new(app, options)
end
Capybara.configure do |config|
config.default_driver = :pg_billy
config.javascript_driver = :pg_billy
end
テストを書いてみる
テストコードはこんな感じです。
require 'rails_helper'
feature 'Login' do
background do
Billy.config.record_stub_requests = true
end
given(:url) { "http://www.example.com" }
scenario 'login' do
proxy.stub(url).and_return(body: File.read("spec/features/htmls/login.html"))
visit url
within("#form") do
fill_in 'id', with: 'id'
fill_in 'password', with: 'password'
end
stub = proxy.stub(url, method: 'post').and_return(
headers: { 'Access-Control-Allow-Origin' => '*' },
code: 200,
text: "Success"
)
click_button('ログイン')
request_params = stub.requests.shift[:body].split("&")
expect(page).to have_content("Success")
expect(request_params).to include("id=id", "password=password")
end
end
ポイント1
Billy.config.record_stub_requests = true
フィールドに値が入って、ちゃんとPostされているかチェックするため、リクエスト情報を記録するようにしています。
ポイント2
proxy.stub(url).and_return(body: File.read("spec/features/htmls/login.html"))
指定のURLにアクセスした際に、用意したHTMLをbodyに入れて返すようにしています。
ポイント3
stub = proxy.stub(url, method: 'post').and_return(
headers: { 'Access-Control-Allow-Origin' => '*' },
code: 200,
text: "Success"
)
ログイン処理をstub化しています。
最後に、フィールドに値がちゃんと入っていること、ログインボタンが押されたことをチェックして、テストは完了です。
なかなか情報もなく、いろいろ悩んだ末、今回このようにテストしてみました。
「うちはこうやってるよ」とかアドバイスいただけるとありがたいです!
参考
Rubyでやるならこの本はオススメです!