Skip to content
Browse files

it_should_behave_like generates a nested example group

- cleanly supports passing a block or not
- does not support using super when replacing behaviour within the group
  • Loading branch information...
1 parent 30bbb6c commit cefe96112be1ff6d68af09fff6f3cc33b4dbe204 @dchelimsky dchelimsky committed Jul 16, 2010
View
2 features/example_groups/shared_example_group.feature
@@ -34,7 +34,9 @@ Feature: Shared example group
When I run "rspec ./shared_example_group_spec.rb"
Then the output should contain "4 examples, 0 failures"
+ @wip
Scenario: Defining a helper method for a shared example group
+ # Need to decide whether to support super() behaviour
Given a file named "shared_example_group_with_helper_method_block.rb" with:
"""
class MyArray < Array; end
View
43 lib/rspec/core/example_group.rb
@@ -60,23 +60,12 @@ class << self
alias_example_to :pending, :pending => true
def self.it_should_behave_like(*names, &customization_block)
- names.each do |name|
+ names.map do |name|
shared_block = RSpec.world.shared_example_groups[name]
raise "Could not find shared example group named #{name.inspect}" unless shared_block
-
- module_eval &shared_block
-
- if customization_block
- # in order to allow the overriden methods in the customization block
- # to super to the base definitions in our shared block, the methods need
- # to be defined in an ancestor. Here we extract the methods and put them
- # in a module that we include/extend so they are available in an ancestor.
- instance_methods, class_methods = extract_method_defs_from(shared_block)
- include define_module(instance_methods)
- extend define_module(class_methods)
-
- module_eval &customization_block
- end
+ shared_group = describe("it should behave like #{name}", &shared_block)
+ shared_group.class_eval &customization_block if customization_block
+ shared_group
end
end
@@ -189,6 +178,7 @@ def self.eval_after_alls(example)
end
def self.run(reporter)
+ @reporter = reporter
example_group_instance = new
reporter.add_example_group(self)
begin
@@ -259,29 +249,6 @@ def self.mixins
:extend => extended_modules
}
end
-
- def self.extract_method_defs_from(block)
- klass = Class.new do
- # swallow any missing class method errors (such as #it and #before);
- # we only care to capture the raw method definitions here.
- def self.method_missing(*a); end
- class_eval(&block)
- end
-
- instance = klass.new
- instance_methods = klass.instance_methods(false).map { |m| instance.method(m) }
- class_methods = klass.singleton_methods.map { |m| klass.method(m) }
-
- return instance_methods, class_methods
- end
-
- def self.define_module(methods)
- Module.new do
- methods.each do |m|
- define_method(m.name, &m)
- end
- end
- end
end
end
end
View
81 spec/rspec/core/shared_example_group_spec.rb
@@ -34,27 +34,16 @@ module RSpec::Core
describe "including shared example_groups using #it_should_behave_like" do
- it "should make any shared example_group available at the correct level", :ruby => 1.8 do
+ it "should make any shared example_group available at the correct level" do
group = ExampleGroup.describe('fake group')
block = lambda {
def self.class_helper; end
def extra_helper; end
}
RSpec.world.stub(:shared_example_groups).and_return({ :shared_example_group => block })
- group.it_should_behave_like :shared_example_group
- group.instance_methods.should include('extra_helper')
- group.singleton_methods.should include('class_helper')
- end
-
- it "should make any shared example_group available at the correct level", :ruby => 1.9 do
- group = ExampleGroup.describe
- shared_examples_for(:shared_example_group) do
- def self.class_helper; end
- def extra_helper; end
- end
- group.it_should_behave_like :shared_example_group
- group.instance_methods.should include(:extra_helper)
- group.singleton_methods.should include(:class_helper)
+ shared_group = group.it_should_behave_like(:shared_example_group).first
+ shared_group.instance_methods.map {|m| m.to_s }.should include('extra_helper')
+ shared_group.singleton_methods.map {|m| m.to_s}.should include('class_helper')
end
it "raises when named shared example_group can not be found" do
@@ -64,7 +53,7 @@ def extra_helper; end
end.should raise_error(/Could not find shared example group named/)
end
- it "adds examples to current example_group using it_should_behave_like" do
+ it "does not add examples to current example_group using it_should_behave_like" do
group = ExampleGroup.describe("example_group") do
it("i was already here") {}
end
@@ -78,32 +67,9 @@ def extra_helper; end
group.it_should_behave_like("shared example_group")
- group.examples.size.should == 3
- end
-
- it "adds examples to from two shared groups" do
- group = ExampleGroup.describe("example_group") do
- it("i was already here") {}
- end
-
group.examples.size.should == 1
-
- group.share_examples_for('test 2 shared groups') do
- it("shared example") {}
- it("shared example 2") {}
- end
-
- group.share_examples_for('test 2 shared groups 2') do
- it("shared example 3") {}
- end
-
- group.it_should_behave_like("test 2 shared groups")
- group.it_should_behave_like("test 2 shared groups 2")
-
- group.examples.size.should == 4
end
-
it "adds examples to current example_group using include", :compat => 'rspec-1.2' do
share_as('Cornucopia') do
it "is plentiful" do
@@ -115,54 +81,46 @@ def extra_helper; end
group.examples.first.metadata[:description].should == "is plentiful"
end
- it "adds examples to current example_group using it_should_behave_like with a module" do
- group = ExampleGroup.describe("example_group") {}
-
- shared_foo = group.share_as(:FooShared) do
- it("shared example") {}
- end
-
- group.it_should_behave_like(::FooShared)
-
- group.examples.size.should == 1
- end
-
it "adds the helper methods from the block provided to it_should_behave_like" do
group = ExampleGroup.describe("example group") {}
group.shared_examples_for("shared group") {}
- group.it_should_behave_like("shared group") do
+ shared_groups = group.it_should_behave_like("shared group") do
def helper_method; end
def self.class_helper; end
end
- group.instance_methods.map { |m| m.to_sym }.should include(:helper_method)
- group.singleton_methods.map { |m| m.to_sym }.should include(:class_helper)
+ shared_group = shared_groups.first
+
+ shared_group.instance_methods.map { |m| m.to_sym }.should include(:helper_method)
+ shared_group.singleton_methods.map { |m| m.to_sym }.should include(:class_helper)
end
it "overrides the instance helper methods with the definitions from the block provided to it_should_behave_like" do
+ pending("decide that we really want this behavior")
group = ExampleGroup.describe("example group") {}
group.shared_examples_for("shared group") do
def helper_method; 'base helper'; end
end
- group.it_should_behave_like("shared group") do
+ shared_groups = group.it_should_behave_like("shared group") do
def helper_method; [super, 'overridden helper'].join('; '); end
end
- group.new.helper_method.should == 'base helper; overridden helper'
+ shared_groups.first.new.helper_method.should == 'base helper; overridden helper'
end
it "overrides the class helper methods with the definitions from the block provided to it_should_behave_like" do
+ pending("decide that we really want this behavior")
group = ExampleGroup.describe("example group") {}
group.shared_examples_for("shared group") do
def self.helper_method; 'base helper'; end
end
- group.it_should_behave_like("shared group") do
+ shared_groups = group.it_should_behave_like("shared group") do
def self.helper_method; [super, 'overridden helper'].join('; '); end
end
- group.helper_method.should == 'base helper; overridden helper'
+ shared_groups.first.helper_method.should == 'base helper; overridden helper'
end
it "allows the RSpec DSL to be used in the block provided to it_should_behave_like" do
@@ -190,7 +148,7 @@ def self.helper_method; [super, 'overridden helper'].join('; '); end
}
end
- describe "running shared examples" do
+ describe "running shared examples", :pending => true do
module ::RunningSharedExamplesJustForTesting; end
let(:group) do
@@ -217,6 +175,7 @@ def count(scope)
end
end
+ # TODO - necessary?
def magic
$magic ||= {}
end
@@ -242,8 +201,10 @@ def count(scope)
group.run_all
end
+ let(:shared_group) { group.children.first }
+
it "runs before(:all) only once from shared example_group", :compat => 'rspec-1.2' do
- group.magic[:before_all].should eq("before all 1")
+ shared_group.magic[:before_all].should eq("before all 1")
end
it "runs before(:each) from shared example_group", :compat => 'rspec-1.2' do

0 comments on commit cefe961

Please sign in to comment.
Something went wrong with that request. Please try again.