rspec-rails と capybara をアップデートしたら request spec で click_link が使えなくなったという声を隣席のぱーらー氏方面から聞こえてきたので、ちゃんとコードを読んで新人's に展開しました。
ぶっちゃけ spec_helper.rb で include Capybara::DSL
してしまえば動くんですが、rspec や capybara という Rails でテストを書く上で無くてはならないライブラリの間でどのような方法が良いということになったのかを知ることは Rails Way に乗る上で大事なことです。
それぞれがどのように動いているかを理解するにはまず最初に example group というものを読むと理解が進みます。
https://github.com/rspec/rspec-rails/blob/master/lib/rspec/rails/example.rb
例えば request spec と呼ばれるものは何かというと
c.include RSpec::Rails::RequestExampleGroup, :type => :request, :example_group => {
:file_path => c.escaped_path(%w[spec (requests|integration|api)])
}
このように書くと spec/{requests,integration,api} というフォルダの下にある *_spec.rb を RequestExampleGroup の対象として処理する。requests だけじゃなくて integration とか api ってディレクトリ名でもいいんですねえ。へー。
さて、次に RequestExampleGroup では何をやっているのかというのを調べます。
https://github.com/rspec/rspec-rails/blob/master/lib/rspec/rails/example/request\_example\_group.rb
module RSpec::Rails
module RequestExampleGroup
extend ActiveSupport::Concern
include RSpec::Rails::RailsExampleGroup
include ActionDispatch::Integration::Runner
include ActionDispatch::Assertions
include RSpec::Rails::Matchers::RedirectTo
include RSpec::Rails::Matchers::RenderTemplate
include ActionController::TemplateAssertions
見ての通り、ActionDispatch の Assertion や RSpec のマッチャは include しているものの capybara っぽいものは何処にもありません。これだと当然 Capybara::DSL は使えるわけありません。
コミットログを見てみると capybara の作者の jnicklas がなにやら feature spec というものを追加していることを見つけました。
https://github.com/rspec/rspec-rails/commit/0fda98b77b43d785e095b6f525840f7d233d9a1d
なるほど、新しく spec/features という example group を追加して、これまで request spec と呼ばれていたものは feature spec というものになったと。
https://github.com/rspec/rspec-rails/blob/master/lib/rspec/rails/example/feature\_example\_group.rb
def visit(*)
if defined?(super)
super
else
raise "Capybara not loaded, please add it to your Gemfile:\n\ngem \"capybara\""
end
end
FeatureExampleGroup を見てみると、確かに Capybara の下準備のようなコードがあります。また、capybara を Gemfile に追加しないで visit を実行しようとするとエラーも表示されるようになっています。
実際に Capybara::DSL を include しているのは、https://github.com/rspec/rspec-rails/blob/master/lib/rspec/rails/vendor/capybara.rb でやっているようです。
このファイルを見ると capybara の rspec と rails をそれぞれ require した後、rspec-rails で作られる ExampleGroup にそれぞれ Capybara の機能を include していることがわかります。
if defined?(Capybara)
RSpec.configure do |c|
if defined?(Capybara::DSL)
c.include Capybara::DSL, :type => :controller
c.include Capybara::DSL, :type => :feature
end
上のように visit や click_link は controller spec と feature spec で使えるんですね。なるほどー。
ここまでは Rails の話ですが、RSpec 単体で Capybara を使う時にも feature spec というようにリネームされていることが capybara/rspec を読むとわかります。
https://github.com/jnicklas/capybara/blob/master/lib/capybara/rspec.rb
RSpec.configure do |config|
config.include Capybara::DSL, :type => :feature
config.include Capybara::RSpecMatchers, :type => :feature
まとめると
require "rspec/rails"
するだけで rspec-rails 準拠の環境になるということのようです。
前回が 2012-08-25 なので、だいたい3ヶ月。