Skip to content

Commit

Permalink
Added thorough tests for shared examples with Aaron Bedra
Browse files Browse the repository at this point in the history
  • Loading branch information
spicycode committed Sep 6, 2009
1 parent eb0020c commit fc71312
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 126 deletions.
3 changes: 3 additions & 0 deletions TODO.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
* in rake task definitions
* formatters

* For self testing
** shared example groups should not be merged into the real 'world'

### Maxwell

* need to figure out how maxwell will allow us to mix all the rails testing
Expand Down
4 changes: 3 additions & 1 deletion lib/rspec/core/example_group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,9 @@ def self.file_path
def self.describe(*args, &behaviour_block)
raise(ArgumentError, "No arguments given. You must a least supply a type or description") if args.empty?
raise(ArgumentError, "You must supply a block when calling describe") if behaviour_block.nil?


# TODO: Pull out the below into a metadata object, that we can defer the subclassing if necessary
# describe 'foo', :shared => true will need this to be completed first
subclass('NestedLevel') do
args << {} unless args.last.is_a?(Hash)
args.last.update(:behaviour_block => behaviour_block)
Expand Down
10 changes: 9 additions & 1 deletion lib/rspec/core/shared_behaviour.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ module Core
module SharedBehaviour

def share_examples_for(name, &block)
ensure_shared_example_group_name_not_taken(name)
Rspec::Core.world.shared_behaviours[name] = block
end

def share_as(name, &block)
if Object.const_defined?(name)
puts "name was defined as #{name.inspect}"
raise NameError, "The first argument (#{name}) to share_as must be a legal name for a constant not already in use."
end

Expand All @@ -26,6 +26,14 @@ def self.included(kls)

alias :shared_examples_for :share_examples_for

private

def ensure_shared_example_group_name_not_taken(name)
if Rspec::Core.world.shared_behaviours.has_key?(name)
raise ArgumentError.new("Shared example group '#{name}' already exists")
end
end

end
end
end
Expand Down
123 changes: 0 additions & 123 deletions spec/rspec/core/example_group_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -226,129 +226,6 @@ def empty_behaviour_group(name='Empty ExampleGroup Group')

end

describe "including shared behaviours using #it_should_behave_like" do

def cleanup_shared_behaviours
original_shared_behaviours = Rspec::Core.world.shared_behaviours
yield if block_given?
Rspec::Core.world.shared_behaviours.replace(original_shared_behaviours)
end

it "should module_eval any found shared behaviours" do
group = empty_behaviour_group
block1 = lambda {}
block2 = lambda {
def extra_helper
'extra_helper'
end
}
Rspec::Core.world.stubs(:shared_behaviours).returns({ :a => block1, :shared_behaviour => block2 })
group.expects(:module_eval).once
group.it_should_behave_like :shared_behaviour
end

it "should make any shared behaviour available at the correct level" do
group = empty_behaviour_group
block = lambda {
def self.class_helper; end
def extra_helper; end
}
Rspec::Core.world.stubs(:shared_behaviours).returns({ :shared_behaviour => block })
group.it_should_behave_like :shared_behaviour
with_ruby(1.8) do
group.instance_methods.should include('extra_helper')
group.singleton_methods.should include('class_helper')
end
with_ruby(1.9) do
group.instance_methods.should include(:extra_helper)
group.singleton_methods.should include(:class_helper)
end
end

it "should raise when named shared example_group can not be found"

it "adds examples to current example_group using it_should_behave_like" do
cleanup_shared_behaviours do
group = empty_behaviour_group("example_group") do |g|
g.it("i was already here") {}
end

group.examples.size.should == 1

group.share_examples_for('shared example_group') do
it("shared example") {}
it("shared example 2") {}
end

group.it_should_behave_like("shared example_group")

group.examples.size.should == 3
end
end

it "adds examples to from two shared groups" do
cleanup_shared_behaviours do
group = empty_behaviour_group("example_group") do |g|
g.it("i was already here") {}
end

group.examples.size.should == 1

group.share_examples_for('shared example_group') do
it("shared example") {}
it("shared example 2") {}
end

group.share_examples_for('shared example_group 2') do
it("shared example 3") {}
end

group.it_should_behave_like("shared example_group")
group.it_should_behave_like("shared example_group 2")

group.examples.size.should == 4
end
end

pending "adds examples to current example_group using include", :compat => 'rspec-1.2' do
shared_example_group = describe "all things", :shared => true do
it "should do stuff" do end
end

example_group = describe "one thing" do
include shared_example_group
end

example_group.number_of_examples.should == 1
end

it "adds examples to current example_group using it_should_behave_like with a module" do
cleanup_shared_behaviours do
group = empty_behaviour_group("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
end

it "runs shared examples", :compat => 'rspec-1.2'

it "runs before(:each) and after(:each) from shared example_group", :compat => 'rspec-1.2'

it "should run before(:all) and after(:all) only once from shared example_group", :compat => 'rspec-1.2'

it "should include modules, included into shared example_group, into current example_group", :compat => 'rspec-1.2'

it "should make methods defined in the shared example_group available in consuming example_group", :compat => 'rspec-1.2'

end


describe Object, "describing nested behaviours", :little_less_nested => 'yep' do

describe "A sample nested describe", :nested_describe => "yep" do
Expand Down
158 changes: 157 additions & 1 deletion spec/rspec/core/shared_behaviour_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@
Kernel.should respond_to(:share_as)
end

it "should complain when adding a second shared behaviour with the same name"
it "should raise an ArgumentError when adding a second shared behaviour with the same name" do
group = double_describe('example group')
group.share_examples_for('really important business value') { }
lambda do
group.share_examples_for('really important business value') { }
end.should raise_error(ArgumentError, "Shared example group 'really important business value' already exists")
end

describe "share_examples_for" do

Expand All @@ -25,5 +31,155 @@

end

describe "including shared behaviours using #it_should_behave_like" do

def cleanup_shared_behaviours
original_shared_behaviours = Rspec::Core.world.shared_behaviours
yield if block_given?
Rspec::Core.world.shared_behaviours.replace(original_shared_behaviours)
end

it "should module_eval any found shared behaviours" do
group = double_describe('fake group')
block1 = lambda {}
block2 = lambda {
def extra_helper
'extra_helper'
end
}
Rspec::Core.world.stubs(:shared_behaviours).returns({ :a => block1, :shared_behaviour => block2 })
group.expects(:module_eval).once
group.it_should_behave_like :shared_behaviour
end

it "should make any shared behaviour available at the correct level" do
group = double_describe('fake group')
block = lambda {
def self.class_helper; end
def extra_helper; end
}
Rspec::Core.world.stubs(:shared_behaviours).returns({ :shared_behaviour => block })
group.it_should_behave_like :shared_behaviour
with_ruby(1.8) do
group.instance_methods.should include('extra_helper')
group.singleton_methods.should include('class_helper')
end
with_ruby(1.9) do
group.instance_methods.should include(:extra_helper)
group.singleton_methods.should include(:class_helper)
end
end

it "should raise when named shared example_group can not be found"

it "adds examples to current example_group using it_should_behave_like" do
cleanup_shared_behaviours do
group = double_describe("example_group") do |g|
g.it("i was already here") {}
end

group.examples.size.should == 1

group.share_examples_for('shared example_group') do
it("shared example") {}
it("shared example 2") {}
end

group.it_should_behave_like("shared example_group")

group.examples.size.should == 3
end
end

it "adds examples to from two shared groups" do
cleanup_shared_behaviours do
group = double_describe("example_group") do |g|
g.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
end

share_as('Cornucopia') do
it "should do foo"
end

it "adds examples to current example_group using include", :compat => 'rspec-1.2' do
group = double_describe('group') { include Cornucopia }
group.should have(1).example
end

it "adds examples to current example_group using it_should_behave_like with a module" do
cleanup_shared_behaviours do
group = double_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
end

describe "running shared examples" do
module RunningSharedExamplesJustForTesting; end

share_examples_for("it runs shared examples") do
include RunningSharedExamplesJustForTesting

def magic
@magic ||= {}
end

before(:each) { magic[:before_each] = 'each' }
after(:each) { magic[:after_each] = 'each' }
before(:all) { magic[:before_all] = 'all' }
end

it_should_behave_like "it runs shared examples"

it "runs before(:each) from shared example_group", :compat => 'rspec-1.2' do
magic[:before_each].should == 'each'
end

it "runs after(:each) from shared example_group", :compat => 'rspec-1.2'

it "should run before(:all) only once from shared example_group", :compat => 'rspec-1.2' do
magic[:before_all].should == 'all'
end

it "should run after(:all) only once from shared example_group", :compat => 'rspec-1.2'

it "should include modules, included into shared example_group, into current example_group", :compat => 'rspec-1.2' do
running_example.behaviour.included_modules.should include(RunningSharedExamplesJustForTesting)
end

it "should make methods defined in the shared example_group available in consuming example_group", :compat => 'rspec-1.2' do
# TODO: Consider should have_method(...) simple matcher
with_ruby('1.8') { running_example.behaviour.methods.should include('magic') }
with_ruby('1.9') { running_example.behaviour.methods.should include(:magic) }
end

end

end


end
8 changes: 8 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ def isolate_behaviour
end
end

def double_describe(*args)
group = Rspec::Core::ExampleGroup.describe(*args) {}
remove_last_describe_from_world
yield group if block_given?
group
end

def use_formatter(new_formatter)
original_formatter = Rspec::Core.configuration.formatter
Rspec::Core.configuration.instance_variable_set(:@formatter, new_formatter)
Expand All @@ -60,6 +67,7 @@ def not_in_editor?

Rspec::Core.configure do |c|
c.mock_framework = :mocha
c.formatter = :documentation
c.filter_run :focused => true
c.color_enabled = not_in_editor?
end

0 comments on commit fc71312

Please sign in to comment.