Ruby
Rails
RSpec
Capybara

Capybaraチートシート

More than 1 year has passed since last update.

当文書はRails + Rspec + Capybara環境を想定しています。
他のアプリ/テストフレームワークを利用したい場合は公式のREADMEを参照願います。

概要

Capybara = UIテストのためのrubyフレームワーク

  • オープンソース / MITライセンス
  • ページの表示、フォームの入力、ボタンのクリック等のUI操作をテストコード上で実行できる

  • 複数のテストフレームワークから利用できる

    • MiniTest, RSpec, Cucumberなど
  • 複数の ドライバ (テスト環境, ヘッドレスブラウザ)を選択して利用できる

    • Rack::Test, Selenium, Webkitなど

導入

インストール

gemをインストールする。
Railsの場合、バージョンによってはデフォルトでGemfileに追加されている。

Gemfile
group :development, :test do
+  # Capybara本体
+  gem 'capybara'
+
+  # Capybaraが利用するドライバを任意に追加する
+  gem 'selenium-webdriver'
+  gem 'capybara-webkit'
end
$ bundle install

RSpecで利用する場合は、スペックのヘルパファイルに記述を追加する。

spec/spec_helper.rb
+ require 'capybara/rspec'

ドライバの選択

Capybaraはテストを実行する環境(ヘッドレスブラウザ)を選択できる。

ドライバの種類 Capybaraにおけるシンボル 概要
Rack::Test :rack_test デフォルト。 Rails標準のテスト機能。Rackと通話して通信をシミュレートする。高速だがJavaScriptを使えない、Rackアプリ外の通信をテストできない。
Selenium :selenium js利用時のデフォルト。Selenium Web DriverによりFirefoxをヘッドレスブラウザとして起動し、その中でテストする。多機能だがFirefoxに依存する。
Webkit :webkit QtWebkitを使ったヘッドレスブラウザ環境。Webkit準拠、Seleniumより高速。
Poltergeist :poltergeist PhantomJSベースのヘッドレスブラウザ環境。ピュアヘッドレス(のため高速)、Webkit準拠。

ドライバは、Capybara全体のデフォルト設定として変更することができる:

spec/spec_helper.rbなど
# ドライバを設定(デフォルトは:rack_test)
Capybara.default_driver = :rack_test

# jsオプション有効時のドライバを設定(デフォルトは:selenium)
Capybara.javascript_driver = :selenium

RSpecの場合

通常はデフォルトのドライバ(default_driver)が使われる。
RSpecにおいてJavaScriptシミュレーションを使いたいスペック/検査は、js: trueを指定することでjavascript_driverが使われる。

some_spec.rb
describe '...', js: true do
  # javascriptが有効になる
end

また、スペック/検査ごとに明示的にドライバを指定して差し替えることもできる。

some_spec.rb
describe '...', driver: :selenium
  # このdescribe内に限り、Seleniumが使われる
end

スペック内で一時的にドライバを差し替えることも可。

some_spec.rb
# 一時的にドライバを変更
Capybara.current_driver = :selenium

# ...

# 元に戻す
Capybara.use_default_driver

DSL

RSpecにおいてCapybaraはビュースペック spec/views/* あるいはフィーチャースペック spec/features/* において利用する。
Capybaraの機能は、RSpecと同じくテストを記述的に実装するためにDSLとして提供されている。

機能の全容は公式のRDocを参照のこと。
以下、主要な機能のみ抜粋する。

locator

Capybaraにおける要素の指定は、locator文字列によって操作対象の要素を指定する。

locatorには以下のような文字列を指定できる:

  • 対象の要素のid属性の値
  • 対象の要素のname属性の値
  • 対象の要素のinner HTML の値
  • 対象の要素に対応する<label>の値(inner HTML)

たとえば以下のビューにあるリンクをテストしたい場合、

app/views/demo/index.html.erb
<a href="path/to/foo" id="id-link-foo">Link Foo</a>

以下のように複数の方法で対象を指定できる。

spec/features/demo_spec.rb
# IDで指定する
click_link 'id-link-foo'

# inner HTMLで指定する
click_link 'Link Foo'

メソッドによっては、HTMLタグ名、CSSセレクタ、XPathなどによって指定することもできる。
詳細はメソッドごとの公式のリファレンスを参照のこと。

ページにアクセスする(Capybara::Session)

visit

visitでページへアクセスする(GETリクエスト)。

visit 'path/to/target`

visitでページアクセスすると、page変数に格納されるCapybara::Sessionオブジェクトが更新される。
後述のAction, Matcher, Finderなどは 暗黙的に このページオブジェクトに対して操作を実行する。

要素を操作する(Capybara::Node)

Capybaraは要素を検索し、操作したり内容を検証したりできる。
各メソッドは要素オブジェクト(Capybara::Node)に対するインスタンスメソッドとして動作するが、
省略した場合(Capybaraのクラスメソッドとして記述した場合)はvisitで取得したページpageに対して適用される。

要素を検索する(Capybara::Node::Finder)

Finderを使うことで、visitで得られたページに含まれる特定の要素を検索・操作できる。

メソッド 動作
`find('locator') 要素を検索
all('tag') HTMLタグにより要素を検索し、全件取得
all(:css, 'selector') cssセレクタにより要素を検索し、全件取得
all(:xpath, 'selector') XPathにより要素を検索し、全件取得
`first(:css, 'locator') 最初に見つかった要素を取得
`find_button('locator') ボタンを検索
`find_by_id('id') IDにより検索
`find_field('locator') テキストフィールドを検索
`find_link('locator') リンクタグを検索

要素の状態を確認する(Capybara::Node::Element)

Finderにより取得した要素(Element)は、その状態を確認できる。

メソッド 動作
[:foo] 属性fooの値を取得
checked? チェック状態を取得
disabled? 無効状態を取得
multiple? multiple属性を取得
path XPathを取得
readonly? readonly属性を取得
selected? プルダウンの選択状態を取得
tag_name タグ名を取得
text innerHTMLを取得
value value属性を取得
visible? 可視状態を取得

また要素を操作できる。

メソッド 動作
click クリックを実行
double_click ダブルクリックを実行
drag_to(elem) 別の要素にドラッグする
hover hover状態にする
right_click 右クリックする
select_option プルダウンを選択
send_keys('text') キー入力
set('text') フォーム要素に対してテキストを入力
trigger('click') イベントをトリガする
unselect_option プルダウンの選択状態を解除

UIを操作する(Capybara::Node::Actions)

Elementのメソッドの他、Capybara::Node::Actions のメソッドでもUIの操作が可能。

メソッド 動作
click_button('locator') ボタンをクリックする
click_link('locator') リンクをクリックする
click_on('locator') ボタンあるいはリンクをクリックする(click_link_or_buttonのエイリアス)
fill_in('locator', with: 'text') テキストボックスに入力する
check('locator') チェックボックスをチェックする
uncheck('locator') チェックボックスのチェックを外す
select('option value' from: 'select locator') セレクトボックスを選択状態にする
`unselect('option value' from: 'select locator') セレクトボックスを非選択状態にする
choose('locator') ラジオボタンを選択する
attach_file('locator', 'path/to/file') ファイルセレクタにファイルを設定する

要素の内容を確認する(Capybara::Node::Matcher)

UIの存在確認のための検索メソッドは、Capybara::Node::Matchersに含まれる。
詳細は公式のRDocを参照のこと。

matcherは、ElementあるいはSession(page)オブジェクトに対してインスタンスメソッドのかたちで実行できる。

page.has_css?('.target_class')

あるいは、RSpecのMatcherとしても書ける。

expect(page).to have_css('.target_class')
メソッド 動作
has_button?('locator') ボタンの存在確認
has_checked_field?('locator') チェック状態のチェックボックスの存在確認
has_css?('selector') CSS定義の存在確認
has_field?('locator') フィールドの存在確認
has_link?('locator') リンクの存在確認
has_select?('locator') プルダウンの存在確認
has_selector?('selector') セレクタの存在確認
has_table?('locator') テーブルの存在確認
has_text?('text') 文言の存在確認
has_unchecked_field?('locator') チェックされていないラジオボタンの存在確認
`has_xpath?('path') XPathの存在確認
has_no_button?('locator') ボタンの存在確認(否定)
has_no_checked_field?('locator') チェック状態のチェックボックスの存在確認(否定)
has_no_css?('selector') CSS定義の存在確認(否定)
has_no_field?('locator') フィールドの存在確認(否定)
has_no_link?('locator') リンクの存在確認(否定)
has_no_select?('locator') プルダウンの存在確認(否定)
has_no_selector?('selector') セレクタの存在確認(否定)
has_no_table?('locator') テーブルの存在確認(否定)
has_no_text?('text') 文言の存在確認(否定)
has_no_unchecked_field?('locator') チェックされていないラジオボタンの存在確認(否定)
`has_no_xpath?('path') XPathの存在確認(否定)
matches_css?('locator') 対象が指定のCSS定義に該当する
matches_selector?('selector') 対象が指定のセレクタに該当する
matches_xpath?('xpath') 対象が指定のXPathに該当する
not_matches_css?('locator') 対象が指定のCSS定義に該当する
not_matches_selector?('selector') 対象が指定のセレクタに該当する
not_matches_xpath?('xpath') 対象が指定のXPathに該当する

アサーションメソッドも存在する。

メソッド 動作
assert_all_of_selectors(:css, 'selector'...) 指定のセレクタがすべて対象内に存在することを確認
assert_matches_selector('selector'...) 対象が指定のすべてのセレクタに合致することを確認
assert_selector('selector') 対象かその子孫が指定したセレクタに合致することを確認
assert_text('text'...) 対象のinnerHTMLが指定のテキストを含むこと
assert_none_of_selectors(:css, 'selector'...) 対象が指定のすべてのセレクタに合致することを確認(否定)
assert_not_matches_selector('selector'...) 対象が指定のすべてのセレクタに合致することを確認(否定)
assert_no_selector('selector') 対象かその子孫が指定したセレクタに合致することを確認(否定)
assert_no_text('text'...) 対象のinnerHTMLが指定のテキストを含むこと(否定)

スコープを切る(within)

withinを使うと、検索/操作の影響範囲を制限することができる。

within(:css, '.target_selector') do
  # 指定したセレクタ内に対してのみ検索/操作が行われる
end
メソッド 動作
within('selector') 指定セレクタに該当する要素以下をスコープとする
within(node) 指定ノード(Element)以下をスコープとする
within_fieldset('locator') 指定のフィールド以下をスコープとする
`within_table('locator') 指定のテーブル以下をスコープとする

ウィンドウを制御する(window)

複数のウィンドウを制御することができる。

メソッド 動作
windows ウィンドウの一覧取得
switch_to_window(window) ウィンドウを選択
window_opened_by({}) ウィンドウを開く(windowオブジェクトを返す)
window_opened_by do ... end ウィンドウを開く(そのまま操作実行)
within_window(window) 指定のウィンドウをスコープとする
window.close ウィンドウを閉じる
window.closed? ウィンドウが閉じられたか確認
window.current? ウィンドウがカレント状態か確認
window.resize_to(w, h) ウィンドウサイズを変える
window.maximize ウィンドウを最大化する
window.size ウィンドウサイズを返す

JavaScriptを実行する(execute_script)

ページ内で任意のJavaScriptを実行できる。

execute_script("'some javascript code'")

評価をruby側に返すこともできる。

ret = evaluate_script("'some javascript code'")

また、Ajaxなどの非同期処理を行う場合、Capybaraはこれを自動的に処理する。
非同期処理のための待ち時間は任意に設定できる。

Capybara.default_max_wait_time = 5

モーダル表示を制御する

アラート表示を操作できる。

メソッド 動作
accept_alert do ... end アラートを補足し、ブロック内で操作する(通常はボタンクリックする)
dismiss_confirm do ... end 確認アラートを補足し、ブロック内で操作する(通常はボタンクリックする)

デバッグする

デバッグのために、ページの情報を取得できる。

メソッド 動作
page.status_code ステータスコードを取得する
page.html そのページのDOMを文字列として取得できる。
page.save_screenshot('screenshot.png') スクリーンショットを取得する

他のアプリ/サーバに接続する

ローカルのRails(Rack App)のほか、任意のサーバに接続できる。

Capybara.app_host = 'http://www.google.com'


# ローカルのRackサーバを使わないことを明示できる
Capybara.run_server = false

参考