On Jul 30, 2010, at 9:03 AM, David Chelimsky wrote:
>
> On Jul 30, 2010, at 5:13 AM, Ashley Moran wrote:
>
>> Hi
>>
>> I finally looked into why this is not currently possibly in RSpec 2 (beta
>> 19):
>>
>> shared_examples_for "Etymology" do
>> describe "The etymology of foo" do
>> it "is followed by #{after_foo}" do
>> # ...
>> end
>> end
>> end
>>
>> describe "foo", focus: true do
>> it_should_behave_like "Etymology" do
>> def self.after_foo
>> "bar"
>> end
>> end
>> end
>>
>> It's because of the current implementation of
>> ExampleGroup.define_shared_group_method, which evaluates the shared example
>> block before the customisation block:
>>
>> shared_group = describe("#{report_label} \#{name}", &shared_block)
>> shared_group.class_eval(&customization_block) if customization_block
>>
>> (This is behaviour I found surprising.)
>>
>> However, with a little more metaprogramming jiggery-pokery, you can have
>> them evaluated in the other order:
>>
>> module RSpec
>> module Core
>> class ExampleGroup
>> # ...
>>
>> def self.define_shared_group_method(new_name, report_label=nil)
>> report_label = "it should behave like" unless report_label
>> module_eval(<<-END_RUBY, __FILE__, __LINE__)
>> def self.#{new_name}(name, &customization_block)
>> shared_block = world.shared_example_groups[name]
>> raise "Could not find shared example group named
>> \#{name.inspect}" unless shared_block
>>
>> compound_block = lambda do |*args|
>> module_eval &customization_block if customization_block
>> module_eval &shared_block
>> end
>>
>> shared_group = describe("#{report_label} \#{name}",
>> &compound_block)
>> shared_group
>> end
>> END_RUBY
>> end
>>
>> # ...
>> end
>> end
>> end
>>
>
> Or ...
>
> def self.define_shared_group_method(new_name, report_label=nil)
> report_label = "it should behave like" unless report_label
> module_eval(<<-END_RUBY, __FILE__, __LINE__)
> def self.#{new_name}(name, &customization_block)
> shared_block = world.shared_example_groups[name]
> raise "Could not find shared example group named \#{name.inspect}"
> unless shared_block
>
> describe "#{report_label} \#{name}" do
> module_eval &customization_block if customization_block
> module_eval &shared_block
> end
> end
> END_RUBY
> end
>
>> Would this be a useful improvement to RSpec 2?
>
> Yes
>
>> Any opinions on the order of the block evaluation for shared examples
>
> Makes perfect sense to me. Wanna make a patch with an additional scenario in
> the cuke?
Actually - maybe I spoke to soon. Ordering things this way would mean that you
couldn't do this:
shared_examples_for Enumerable do
def enumerable
raise "you must provide an enumerable method that returns the object which
you're specifying should behave like Enumerable"
end
it "..." { .. }
end
Although, if you were going to do that, I guess you could do this:
shared_examples_for Enumerable do
unless defined?(:enumerable)
raise "you must provide an enumerable method that returns the object which
you're specifying should behave like Enumerable"
end
it "..." { .. }
end
Maybe that, or a DSL that wraps that, is the better way, so we can get the best
of both worlds?
shared_examples_for Enumerable do
require_instance_method :foo, "gotta have foo instance method"
require_class_method :foo, "gotta have foo class method"
require_instance_variable "@foo", "gotta have an instance variable named @foo"
it "..." { .. }
end
Thoughts?
>
>>
>> Cheers
>> Ash
>>
>> --
>> http://www.patchspace.co.uk/
>> http://www.linkedin.com/in/ashleymoran
>>
>> _______________________________________________
>> rspec-users mailing list
>> [email protected]
>> http://rubyforge.org/mailman/listinfo/rspec-users
>
_______________________________________________
rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users