Design flaw with Fixtures?


#1

I’ve been trying to add unit testing for collection of models with
complex relationships – and failing miserably.

Because of the complexity of the relationships, I’m using a database
which validates foreign key constraints (PostgreSQL 8).

I’m finding it nearly impossible to generate tests that are independent
of each other. The basic problem is the DELETE then INSERT nature of
#create_fixtures.

What happens is that one test inserts a bunch of data into the database
and then exits. The next test comes along and tries to perform the
deletes and an exception is raised because one of the fixtures from the
previous test causes a constraint violation.

Of course, there are ways to avoid these problems, but they are either
non-DRY or have a performance impact:

  1. Add #delete_all on all the models during #setup or #teardown. This
    cleans up the tables and allows the tests to run.

  2. Ensure that all models involved in the relationship are a part of the
    #fixtures invocation. When #create_fixtures is run, the contents of all
    tables will be deleted.

The more I look at this problem, the more I see a design flaw in how
fixtures are loaded. The current mechanism is:

  • nuke any existing fixture data
  • load the fixture data
  • load the instance variables
  • run the test

It seems that a smarter way to perform the tests would be to:

  • load the fixture data
  • load the instance variables
  • run the test
  • nuke the fixture data

As it is now, I’m spending more times trying to get fixtures to work and
no time writing tests. The really frustrating thing is that these
complex relationships is the part of the system that need the most
testing.

After 4 months of using Rails, this is the first time I feel let down…

-ch


#2
  • Craig H. (removed_email_address@domain.invalid) [060106 18:51]:

I’ve been trying to add unit testing for collection of models with
complex relationships – and failing miserably.

Because of the complexity of the relationships, I’m using a database
which validates foreign key constraints (PostgreSQL 8).

I’m finding it nearly impossible to generate tests that are independent
of each other. The basic problem is the DELETE then INSERT nature of
#create_fixtures.

Please have a look at: http://dev.rubyonrails.org/ticket/2404

Rick

http://www.rickbradley.com MUPRN: 639
| there should be a
random email haiku | maximum length (e.g. bytes)
| of that descriptions.


#3

On a related note, something I’ve wondered about when defining foreign
key relationships in the database: should this even be done when we
can ensure relationships using validation methods? It seems like this
is a violation of DRY unless another application needs to directly
interact with the database.

  • Derek

On 1/6/06, Rick B. removed_email_address@domain.invalid wrote:

Rails mailing list
removed_email_address@domain.invalid
http://lists.rubyonrails.org/mailman/listinfo/rails


Derek H.
HighGroove Studios - http://www.highgroove.com
Atlanta, GA
Keeping it Simple.
404.593.4879


#4

On Jan 7, 2006, at 3:46 AM, Derek H. wrote:

On a related note, something I’ve wondered about when defining foreign
key relationships in the database: should this even be done when we
can ensure relationships using validation methods? It seems like this
is a violation of DRY unless another application needs to directly
interact with the database.

Check out http://www.loudthinking.com/arc/000516.html for DHH’s take on
this. If you’re only hitting the database from your Rails app, there’s
really no reason to bother with foreign key constraints.

-dudley


#5

Here’s my own take:
http://www.josephmoore.net/2005/12/unit-testing-leave-no-trace-vs-schmutz.html

On our Rails projects, we decided to take the opposite extreme, despite
my
propensity for Leave No Trace vs. Schmutz: we added code to
test_helper.rb
that loads all fixtures during setup. By doing this, we guarantee
that
all data is nuked before tests run, and all tests have the same exact
data
with which to play. And no, we don’t have a ton of fixture data.

At first I was against this, but I’ve come the to conclusion that the
“promise” we make to our tests is not that they will start with a clean
slate, but that they will start from a known starting point; this is not
the
necessarily case with Rails’ current “only delete referenced fixtures”
model. By loading all fixtures, our tests behaved the same regardless
of
“starting-empty” vs. “delete-all-data then load-all-data.”

– Joe