近&況

Recent Posts
Edit

CapybaraでSinatraアプリをテストする

2017-02-28

このブログはSinatraで作っていて、テストはRack::Testで書いてたのだけど、思い立ってCapybaraで書き直した

Rack::Test vs Capybara?

というのはある種のバグがRack::Testだと漏れちゃうんですよね。例えばフォームをsubmitしたときにビューのtypoで正しいリクエストが飛ばない、みたいなやつ。Rack::TestだとこういうPOSTリクエストに対しこういう挙動をする、は書けるんだけど、ボタンを押したときにどういうPOSTが飛ぶか、はCapybaraでないと書けない。

もっと規模が大きければRack::Testでコントローラのテストを書いて、Capybaraでintegraiton testを書いて…みたいな構成もあり得るけど、このブログの場合は規模が小さいのでCapybaraによるE2Eテストだけあれば良いかなと思う。

以下、Rack::Testから移行するに当たって「これどうするんだろ?」ってなったことをメモしておく。

Basic認証したい

Driverによって指定方法が違うみたい。Rack::TestドライバはBasic認証に対応してなさそう。しかしヘッダを直接指定するという方法があった(参考)。

  # https://github.com/yhara/nlog2/blob/a63294a2a1b514e76ac130b2f6400fda8a8436b5/spec/app_spec.rb#L8-L11
  def login(username='jhon', password='passw0rd')
    encoded_login = ["#{username}:#{password}"].pack('m*')
    page.driver.header 'Authorization', "Basic #{encoded_login}"
  end

フォームが表示されることを確認したい

have_content("form")…かと思いきや、これはformというテキストが画面に表示されている、という意味なのでタグには反応しない。have_selector("form")が正解。

フォームにデフォルトで入力されていることを確認したい

これもhave_selectorでいける。こんな感じ。

      expect(page).to have_selector("input[name='title'][value='#{@valid_posted[:title]}']")

POSTしたい

postメソッドがない、と思ったがCapybaraはE2Eテスト用のライブラリなので、POSTリクエストを直接送るような手段はないのだった。そりゃそうか。その代わりにclick_linkやclick_buttonといったメソッドがあるので、まずvisitで編集画面にアクセスして、フォームに記入してclick_buttonする、みたいな書き方になる。

今回はこんな感じにした。

        login
        visit '/_edit/'
        fill_editor @valid_params
        click_button "Save"

fill_editorはcheckメソッドでチェックボックスをオンにしたり、fill_inでテキストを入力したりする。定義は以下。

  def fill_editor(params)
    check "permanent" if params[:permanent]
    fill_in "title", with: params[:title]
    fill_in "slug", with: params[:slug]
    fill_in "body", with: params[:body]
    fill_in "datetime", with: params[:datetime]
  end