RSpec.configure の extend 、 include はどうなっているのか

  • 9
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

RSpec で

module M1
  def hoge
    p 'hoge'
  end
end

module M2
  def fuga
    p 'fuga'
  end
end

RSpec.configure do |c|
  c.extend M1
  c.include M2
end

describe 'test' do
  hoge

  it do
    fuga
  end
end

のように extend で DSL を、 include で example 内で使えるメソッドを追加することができます。
これをどのようにして実現しているのか調べてみました。

RSpec::Core::Configuration#extend 、 include

RSpec.configure のブロック引数である c は RSpec::Core::Configuraion のインスタンスです。
ここで呼び出している extend は、RSpec::Core::Configuraion でオーバーライドしてあります。
Object#extend ではないです。
RSpec::Core::Configuration#extend、include によって extend や include するべきモジュールが登録されます。

extend 、 include 先のクラス

describe もしくは context を呼び出すと、RSpec::Core::ExampleGroup を継承したクラスを作成します。
クラスを作る際に、そのクラスに RSpec::Core::Configuration#extend、include で登録したモジュールが extend 、 include されます。

実行

DSL 部分の解釈は describe 時に作ったクラスに module_eval しているので extend したメソッドを使うことができます。
example 部分の実行は describe 時に作ったクラスのインスタンスに instance_eval しているので include したメソッドを使うことができます。