Rspec-2 around/before(:all) hooks

Rspec-2 around/before(:all) hooks

I’m trying to create several model instances before all of our tests are
run. I’m having trouble defining the behavior in my Rspec.configure
block. I’ve tried before(:all) and around(:all), but to no avail.

before(:all) successfully creates the models, but it appears that
everything in the block passed is rolled back before the test runs:

spec_helper.rb

config.before(:all) do
@person = Person.create(:name => ‘not here!’)
end

person_spec.rb

describe Person
it do
p Person.where(:short_name => ‘not here!’).first #=> nil
p @person #=> <Person id: 1050608284, name: “not here!”>
@person.reload #=> Error: Couldn’t find Person with ID=1050608284
end
end

It seems that around(:all) is not supported, either. Is that correct?
This code in the block passed to configure results in a nil.<< error:

spec_helper.rb

config.around(:all) do
puts “hai”
yield
puts “bai”
end

I’m running rspec-2.0.1 and rails-3.0.0. Is there a preferred way to do
this that I’m missing? Thanks in advance!

On Nov 2, 2010, at 1:54 PM, Mack T. wrote:

config.before(:all) do
end

I’m running rspec-2.0.1 and rails-3.0.0. Is there a preferred way to do
this that I’m missing? Thanks in advance!

A few things:

  1. I can’t reproduce what you’re describing. I get the same person
    object for all three lines in the example (adding a ‘p’ to the last
    line). Not sure why that would be.

  2. around(:all) is not supported (needs a better error message), but
    before(:all) should work.

  3. What you’re trying to do is a bit unusual. By default, each example
    is run in a transaction which is rolled back at the end of the example.
    This keeps all of the examples isolated from each other, which is a very
    desirable outcome. If you use before(:all), the created object will
    remain in the database, so it’s up to you to clean it up yourself
    instead of relying on ActiveRecord to do it for you.

Also, before(:all) (or before(:each)) in the configure block in
spec_helper adds that to every example group. i.e. it’s the same as
declaring that block in each group. If you’re looking to do this once
per run, use before(:suite).

HTH,
David

I should have mentioned this before, but I’m using fixtures in these
specs. When I took all of the fixtures out, I get the same before(:all)
behavior that you got. With them in, it seems whatever happens in the
before(:all) is rolled back before any examples run. Can you reproduce
that behavior with fixtures included?

What I’m really trying to accomplish here is faster examples that don’t
have to repeatedly build the same model relationships. Doubles won’t
work, since I want to make sure models save to the database correctly
and most relationships have foreign key constraints. It would be great
to establish a known setup of models that all examples can assume
exists.

I realize that I’ll have to manually undo whatever changes I do in the
before block, but that’s a price I’m willing to pay. Examples should
remain isolated if the database is restored to the same state it was
when they started.

before(:suite) is looking promising. The instance variables aren’t
available as they are in before(:all), but that’s simple to work around.

Thank you so much for your help!

Any ideas on how to create models in the before(:suite) block in a
transaction, then not commit that transaction and roll it back in the
after(:suite) block?