Forum: RSpec Mixing in spec helper methods

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
49de4cd2f26705785cbef2b15a9df7aa?d=identicon&s=25 Nick Hoffman (nickh)
on 2008-11-12 01:25
(Received via mailing list)
I've written a module for my specs that contains a helper method, and
am mixing the module into my specs with #include . It seems that the
method must be called with an #it block. If it isn't, this error occurs:

... in `method_missing': undefined method
`it_should_behave_like_an_action_that_sets_the_flash_notice' for
Spec::Rails::Example::ControllerExampleGroup::Subclass_1:Class
(NoMethodError) from ./spec/controllers/properties_controller_spec.rb:8

Is there a way to call my helper method from outside of an #it block?
Here's the code:
http://pastie.org/312680

Thanks!
Nick
C694a032be7518a0d704318895f8fe1d?d=identicon&s=25 Ben Mabey (mabes)
on 2008-11-12 01:31
(Received via mailing list)
Nick Hoffman wrote:
> Here's the code:
> http://pastie.org/312680
>
> Thanks!
> Nick
> _______________________________________________
> rspec-users mailing list
> rspec-users@rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
It looks like you want those methods in your module as class method, not
instance methods.  Try extending, not including, your module (extend
AuthSpecHelpers.)  You might want to read my post about creating rspec
macros as well:
http://www.benmabey.com/2008/06/08/writing-macros-in-rspec/

-Ben
42172acdf3c6046f84d644cb0b94642c?d=identicon&s=25 Pat Maddox (pergesu)
on 2008-11-12 01:40
(Received via mailing list)
Nick Hoffman <nick@deadorange.com> writes:

>
> Is there a way to call my helper method from outside of an #it block?
> Here's the code:
> http://pastie.org/312680

You want extend instead of include.

Also, if you want to share this among many example groups, you can do it
in the config block instead of extending it in every single example
group:

Spec::Runner.configure do |config|
  config.extend AuthSpecHelpers
end

You can even do it for particular example group types if you want:

Spec::Runner.configure do |config|
  config.extend AuthSpecHelpers, :type => :controller
end

Pat
5d38ab152e1e3e219512a9859fcd93af?d=identicon&s=25 David Chelimsky (Guest)
on 2008-11-12 01:59
(Received via mailing list)
On Tue, Nov 11, 2008 at 6:39 PM, Pat Maddox <pergesu@gmail.com> wrote:
>> (NoMethodError) from
> group:
>
> Spec::Runner.configure do |config|
>  config.extend AuthSpecHelpers
> end
>
> You can even do it for particular example group types if you want:
>
> Spec::Runner.configure do |config|
>  config.extend AuthSpecHelpers, :type => :controller
> end

Note that config.extend was only added recently, in rspec-1.1.9.

Cheers,
David
49de4cd2f26705785cbef2b15a9df7aa?d=identicon&s=25 Nick Hoffman (nickh)
on 2008-11-12 21:45
(Received via mailing list)
On 2008-11-11, at 19:31, Ben Mabey wrote:
>> properties_controller_spec.rb:8
> not instance methods.  Try extending, not including, your module
> (extend AuthSpecHelpers.)  You might want to read my post about
> creating rspec macros as well:
> http://www.benmabey.com/2008/06/08/writing-macros-in-rspec/
>
> -Ben

That was post was gold, Ben. It cleared up most of my questions and
confusion regarding #include, #extend, and mix-ins. Thanks, mate.
49de4cd2f26705785cbef2b15a9df7aa?d=identicon&s=25 Nick Hoffman (nickh)
on 2008-11-12 21:56
(Received via mailing list)
On 2008-11-11, at 19:39, Pat Maddox wrote:
>> ./spec/controllers/properties_controller_spec.rb:8
> group:
>
> Pat

That's convenient. What I've done is add this to the beginning:
   require 'spec/shared/auth_spec_helpers'

and add this to the 'config' block:
   config.extend AuthSpecHelpers, :type => :controller

of spec_helper.rb . Is that a suitable, or preferred, method of
extending the helper methods in the AuthSpecHelpers module to
controller specs?

Thanks,
Nick
49de4cd2f26705785cbef2b15a9df7aa?d=identicon&s=25 Nick Hoffman (nickh)
on 2008-11-12 21:59
(Received via mailing list)
On 2008-11-11, at 19:49, David Chelimsky wrote:
> David
Thanks for remembering that I'm using an old version of RSpec and
RSpec-Rails, mate  ;)  That was enough of a reason to upgrade, so now
I'm running 1.1.11 of the plugins. Hoorah!
-Nick
49de4cd2f26705785cbef2b15a9df7aa?d=identicon&s=25 Nick Hoffman (nickh)
on 2008-11-12 22:09
(Received via mailing list)
On 2008-11-11, at 19:31, Ben Mabey wrote:
>> properties_controller_spec.rb:8
>> http://rubyforge.org/mailman/listinfo/rspec-users
> It looks like you want those methods in your module as class method,
> not instance methods.  Try extending, not including, your module
> (extend AuthSpecHelpers.)  You might want to read my post about
> creating rspec macros as well:
> http://www.benmabey.com/2008/06/08/writing-macros-in-rspec/
>
> -Ben

After digesting that post again, especially the contents of
#self.included , I noticed that one could alternatively do this:

module AssignMacro
   def self.extended(receiver)
     receiver.extend ExampleGroupMethods
     receiver.send :include, ExampleMethods
   end
end

describe UserPhotosController do
   describe "GET 'users/1/photos/2'" do
     extend AssignMacro
     # ...
   end
end

Is one approach more preferable? Or should one do this so that both
"include AssignMacro" and "extend AssignMacro" give the same, desired,
result?:

module AssignMacro
   def self.included(receiver)
     receiver.extend ExampleGroupMethods
     receiver.send :include, ExampleMethods
   end

   class << self
     alias_method :extended, :included
   end
end

Thanks for your input, guys.
-Nick
C694a032be7518a0d704318895f8fe1d?d=identicon&s=25 Ben Mabey (mabes)
on 2008-11-12 22:38
(Received via mailing list)
Nick Hoffman wrote:
>>> (NoMethodError) from ./spec/controllers/properties_controller_spec.rb:8
>>> http://rubyforge.org/mailman/listinfo/rspec-users
>
>     # ...
>     receiver.send :include, ExampleMethods
> rspec-users mailing list
> rspec-users@rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users

Some people would say that using the included or extended module hooks
like that are evil.[1]  That said it is a very common ruby idiom even if
it is bad.  If you are going to use the evil idiom then I would suggest
using include and not extend since it is the idiom.  :)

Another way to do it that wouldn't take advantage of the evil hooks
would be:

describe UserPhotosController do
  describe "GET 'users/1/photos/2'" do
    extend AssignMacro::ExampleGroupMethods
    include AssignMacro::ExampleMethods
    # ...
  end

Of course that is somewhat annoying to type everywhere.  So perhaps you
could add another example group method that would mix in macors.. likes
so:

describe UserPhotosController do
  describe "GET 'users/1/photos/2'" do
    use_macro AssignMacro
    # ...
  end
end

The 'use_maco' would be a module that you mix in onto all rspec's
example group methods that would simply include and extend the given
module's ExampleMethods and ExampleGroupMethods modules respectively.

The 'use_macro' is probably more clear than the hooks.  Just a thought.

-Ben


1. http://olabini.com/blog/2008/09/evil-hook-methods/
49de4cd2f26705785cbef2b15a9df7aa?d=identicon&s=25 Nick Hoffman (nickh)
on 2008-11-13 19:52
(Received via mailing list)
On 2008-11-12, at 16:38, Ben Mabey wrote:
>>
>>
>>
> would be:
> macors.. likes so:
> module's ExampleMethods and ExampleGroupMethods modules respectively.
>
> The 'use_macro' is probably more clear than the hooks.  Just a
> thought.
>
> -Ben
>
>
> 1. http://olabini.com/blog/2008/09/evil-hook-methods/

The "evil hook methods" article explained exactly how I was feeling.
Everyone's different, but I feel dirty extending the receiver in
#included , and vice versa. I've decided to go along with your first
suggested alternative:

## spec/spec_helper.rb
# ..snip..
Spec::Runner.configure do |config|
   # ..snip..
   config.extend   AuthSpecHelpers::ExampleGroupMethods, :type
=> :controller
   config.include  AuthSpecHelpers::ExampleMethods,      :type
=> :controller
end

Thanks again for taking the time to explain all of this, Ben. I really
learned a lot. Cheers,
Nick
This topic is locked and can not be replied to.