[rspec-users] Database clearing

Pat Maddox pergesu at gmail.com
Fri Sep 19 12:34:16 EDT 2008


"Todd Tyree" <todd at snappl.co.uk> writes:

> I'm seeing something strange and was just wondering if someone can confirm my
> assumptions for me:
>
> I have  user model with a number of specs: some of them use fixtures and some
> of them don't.  Today, while talking someone through some specs that needed
> developming, I noticed that the fixtures always seemed to be loading.  When I
> investigated, I discovered that it was not the fixtures always loading, but the
> db not clearing between runs.  So, given a very simple spec (with the standard
> fixtures):
>
> # -*- coding: mule-utf-8 -*-
> require File.dirname(__FILE__) + '/../spec_helper'
>
> describe User do
>   fixtures :users
>
>   it "should have some users" do
>      User.all.should_not be_blank
>   end
> end
>
> describe User, "description" do
>   it "should not show emails" do
>      User.all.should be_blank
>      # Or, to be a bit more concise:
>     User.all.select{|u| u.email == 'bob at example.com'}.should be_blank
>   end
> end
>
> The second describe is failing because the db is populated with the users from
> fixtures (still).  I am correct in assuming, with transactions fixtures
> switched to true (as it is), this should not be the case, right? 

No, that is not correct.  Here's how transactional fixtures work:

1. Before all specs run, load the fixtures into the database
2. Start a transaction.  Run the first spec
3. Rollback transaction
4. Start another transaction.  Run the second spec
5. Rollback transaction

And that's it.  The transaction part is basically a hack to repopulate
the db more quickly...instead of doing a bunch of inserts before each
example, you just rollback the transaction so the fixtures are clean
again.  This has the effect of bleeding DB data into other example
groups if you're not careful (Mark: does that help to explain the
acerbic comments?).

To my knowledge, there are three main choices:
1. Delete stuff before example
2. Load the fixtures for whatever model you're specifying, and just deal
with the fact that there's stuff in there
3. Don't use Rails db fixtures

I've long been using #3.  There are a couple reasons why, in addition to
the problem you're experiencing.  The first is that I like to do as much
of the setup close to the exaple as possible.  Creating a user in my
'before' means I don't have to look very far to see/understand/modify
the data being used in a particular example.  And the second reason is
that when you use db fixtures, every example that uses them becomes
coupled.  Things will be going fine for a while, and then you have to
change the fixture to support one thing, and then a bunch of other
example start failing as a result.

There's another approach though that I haven't tried yet.  One of the
guys I work with truncates all the tables in the db before every
example.  He says this runs as fast or faster than transactional
fixtures, and has the added benefit of NOT being in a transaction, which
means that if he actually DOES use a transaction in his application code
then he can test it very easily.  I've not tried it, but it seems like a
cool idea.

Pat


More information about the rspec-users mailing list