トップ «前の日記(2012/11/15 (木) ) 最新 次の日記(2012/11/17 (土) )» 編集 RSS feed

HsbtDiary


2012/11/16 (金) [長年日記]

[rspec][ruby][rails] rspec-rails と capybara のまとめ

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

まとめると

  • rspec-rails と capybara をそれぞれ Gemfile に書いて、spec_helper.rb で require "rspec/rails" するだけで rspec-rails 準拠の環境になる
  • features spec というものが導入されて visit や click_link はここで使う
  • request spec は test-unit で言うところの integration test という扱いになったので Capybara::DSL は使えない

ということのようです。

[Life] 散髪記録

前回が 2012-08-25 なので、だいたい3ヶ月。