Forum: RSpec Understanding of extend/include

Posted by Gordon (Guest)
on 2011-12-05 01:18
(Received via mailing list)
hi, there

 I have been looking at
https://www.relishapp.com/rspec/rspec-core/docs/he....

This is the documentation for usage of extend and include.

In the section, "Scenario: extend a module in only some example
groups",
I refer  to the setup in RSpec.configure, "c.extend Helpers, :foo
=> :bar"
implies that the methods in Helpers are available to examples with the
metadata, ":foo=>:bar".

------------- Extract start ---------------

describe "an example group with matching metadata", :foo => :bar do
  puts "In a matching group, help is #{help}"

  it "does not have access to the helper methods defined in the
module" do
    expect { help }.to raise_error(NameError)
  end
end

------------- Extract end   ---------------

Question: Why is the example expected to fail (ie.
raise_error(NameError))
when the meta data matches and it's expected to pass?
Posted by David Chelimsky (Guest)
on 2011-12-05 02:06
(Received via mailing list)
On Dec 4, 2011, at 6:15 PM, Gordon wrote:

> => :bar"
>    expect { help }.to raise_error(NameError)
>  end
> end
>
> ------------- Extract end   ---------------
>
> Question: Why is the example expected to fail (ie.
> raise_error(NameError))
> when the meta data matches and it's expected to pass?

In Ruby, when we include modules in classes, their methods are available 
in instances of those classes.

  module Helper
    def help
      :available
    end
  end

  class Foo
    include Helper
  end

  foo = Foo.new
  foo.help # => :available

We can also make the same methods available by extending an instance of 
a class.

  class Bar
  end

  bar = Bar.new
  bar.extend(Helper)
  bar.help # => :available

Now the tricky part is that classes are objects as well - instances of 
the Class class. This means that when you extend a class, its methods 
are available as class methods, not as instance methods:

  class Baz
    extend Helper
  end

  Baz.help # => :available
  Baz.new.help # => ERROR!!!!!!!

In RSpec, an example group is a class, whereas an example is 
(effectively) an instance of that class. This is not 100% accurate, but 
let's go with that metaphor for the moment. When you say "config.include 
SomeModule", it gets included into example groups, making its methods 
available within examples (instances of the group). When you say 
"config.extend SomeModule", it extends the example group, making its 
methods available within at the group level, but not within the 
examples.

In the scenario you cite, the module is used to extend the example group 
matching :foo => :bar (the first group), so it is available at the group 
level, as demonstrated by `puts "In a matching group, help is #{help}"` 
printing out "In a matching group, help is available", but is not 
available in the other group, as demonstrated by `puts "In a 
non-matching group, help is #{help rescue 'not available'}"` printing 
out "In a non-matching group, help is not available", and it is not 
available to examples (instances) in either group, as demonstrated by 
`expect { help }.to raise_error(NameError)` passing in both examples.

HTH,
David
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.