RSpec中の特定のtypeでmodule を include する

RSpec.configure do |config|
  ...
  config.include(ControllerHelpers, :type => :controller)
  ...
end

Rails tips: テストから共通機能を切り出すリファクタリング(翻訳)|TechRacho(テックラッチョ)〜エンジニアの「?」を「!」に〜|BPS株式会社

こんな感じでtypeに応じてmoduleをincludeすることでそれぞれのtypeのみ有効なhelper methodを定義することができる。

# rails_helper.rb
RSpec.configure do |config|
  ...
  # type: :request な spec のみでincludeされる
  config.include(RequestSpecHelper, type: :request)
  # type: :system な spec のみでincludeされる
  config.include(SystemSpecHelper, type: :system)
  # type: :view な spec のみでincludeされる
  config.include(ViewSpecHelper, type: :view)
  ...
end

assert_select assertion

rspec で自動で generate されるview specにはassert_selectが使われていたので調べた。

assert_selectには2つの書式があります。

assert_select(セレクタ, [条件], [メッセージ])という書式は、セレクタで指定された要素が条件に一致することを主張します。セレクタにはCSSセレクタの式 (文字列) や代入値を持つ式を使えます。

assert_select(要素, セレクタ, [条件], [メッセージ]) は、選択されたすべての要素が条件に一致することを主張します。選択される要素は、element (Nokogiri::XML::Node or Nokogiri::XML::NodeSetのインスタンス) からその子孫要素までの範囲から選択されます。

ref. Rails テスティングガイド - Railsガイド

titleタグとその内部の文字列のチェック。

assert_select 'title', "Welcome to Rails Testing Guide"

ネストして書くことも可能。

assert_select 'ul.navigation' do
  assert_select 'li.menu_item'
end

使ってみた

これをもとに書いたテストがこちら。

特定の form の内部の値が正しくセットされているかを検証している。

assert_select "form[action=?][method=?]", relationship_path, "post" do
  assert_select "input[type=hidden][name=?][value=?]", "relationship[follower_id]", @login_user.id.to_s
  assert_select "input[type=hidden][name=?][value=?]", "relationship[followed_id]", @user.id.to_s
  assert_select "input[type=submit][value=?]", "Unfollow"
end