Testing eager loading of associations

Is there an easy way to test to see if an association has been loaded by
eager-loading already? I’d like to detect (in functional tests) that
comments are eager-loaded when a Post is selected. I can do

assert post.instance_variables.include? ("@comments")

but is that appropriate?

Any ideas? Thanks much!

Brian H. wrote:

Is there an easy way to test to see if an association has been loaded by
eager-loading already? I’d like to detect (in functional tests) that
comments are eager-loaded when a Post is selected. I can do

assert post.instance_variables.include? ("@comments")

but is that appropriate?

Yes, that’d work. Also: assert post.comments.loaded?


We develop, watch us RoR, in numbers too big to ignore.

Brian,

Is there an easy way to test to see if an association has been
loaded by
eager-loading already? I’d like to detect (in functional tests)
that
comments are eager-loaded when a Post is selected. I can do

(not an answer:)
It looks like you are trying to test the framework (Rails). May I ask
why?

Alain

Alain R. wrote:

Brian,

Is there an easy way to test to see if an association has been loaded by
eager-loading already? I’d like to detect (in functional tests) that
comments are eager-loaded when a Post is selected. I can do

(not an answer:)
It looks like you are trying to test the framework (Rails). May I ask why?

He’s probably ensuring that the include option has been correctly
programmed.


We develop, watch us RoR, in numbers too big to ignore.

That should be covered by Rails unit tests.

@luke:

No, I’m testing to ensure that my developers have eager-loaded
associations
in some controller methods. I want the functional tests to fail if they
forgot to eager-load.

We’re doing test-first development here so the devs know when they need
to
eager-load. I just wanted a way for them to test that they did.

Testing

@post = Post.find params[:id]

vs

@post = Post.find params[:id], :include=>[:comments]

Or in a bigger case

def self.find_projects_and_associations
Project.find params[:id], :include=>[{:tasks =>:hours}, :notes,
:attachments, :backlogtasks, :payments, :expenses]
end

A call like this would go into the model… but a developer still has to
use
it. If they use a regular finder.

So I’m not testing to see if eager loading works, I’m testing to see if
the
developer used it :slight_smile:

@Mark:

Thank you!

@Alain:

If your system is too slow, then build a test that fails at the
current speed, and tell them that one way to make the test pass is too
eager load.
In the absence of context, it looks like micro-managing and premature
optimization.

I disagree. There are times when you know you’re going to cause 200+
queries if you don’t eager load. Testing for those cases is, IMHO, not
micromanaging or premature optimization.

Brian

No, I’m testing to ensure that my developers have eager-loaded
associations
in some controller methods. I want the functional tests to fail if
they
forgot to eager-load.

If your system is too slow, then build a test that fails at the
current speed, and tell them that one way to make the test pass is too
eager load.
In the absence of context, it looks like micro-managing and premature
optimization.

We’re doing test-first development here so the devs know when they
need to
eager-load. I just wanted a way for them to test that they did.

Well No: they don’t know they NEED it - there is no failing test- ,
they just know that they HAVE TO write code that way, for some reason.

Alain

On 11/28/06, Alain R. [email protected] wrote:

your eager-loading/caching/indexing needs indirectly.

Alain

I see ensuring the eager load via a test as a way to verify a spec - I
have many actions or associations that I know I always want to eager
load. The right place for that is in a live spec, ie a test case or
rspec context. That certainly doesn’t remove the need for real
performance testing and benchmarking - but often proper eager loading
is the simplest thing that works, and the really nasty cases that need
more tuning will be clear after that.

  • Rob

http://www.ajaxian.com

Brian,

If your system is too slow, then build a test that fails at the
current speed, and tell them that one way to make the test pass is too
eager load.

I disagree. There are times when you know you’re going to cause 200+
queries if you don’t eager load. Testing for those cases is, IMHO, not
micromanaging or premature optimization.

My point is that you are NOT testing that you are solving a
(potential!) problem. You’re JUST ensuring that you have implemented
one possible solution.
You check that the patient takes his vitamins, but not that they are
effective, or even needed.
And why only test eager-loading? What about indexes? Will you test the
schema, to see if they have addedan index on all/a given column. And
what about Caching, Custom selects, Memoizing, etc…
If you write real functional speed/benchmark tests, they will test
your eager-loading/caching/indexing needs indirectly.

Alain

Rob:

Exactly! Thanks!

Rob

I see ensuring the eager load via a test as a way to verify a spec -
I
have many actions or associations that I know I always want to
eager
load.

I see no difference between adding eager-loading, and adding an index
to a table. Do you test the schema for index presence?
When I notice an application is slow, and I see it’s due to a missing
index, I just add the index in a migration, and that’s it. If the
application is still slow, then I add a functional benchmark test, and
I start experimenting.

And I have this funny feeling about checking the implementation, and
not the end-result/interface…

often proper eager loading is the simplest thing that works, and
the really nasty
cases that need more tuning will be clear after that.

I suspect there are cases where unnecessary eager-loading could
actually slow down an operation. The patient takes a double-dose of
his pills, but he’s getting worse. As you are not testing his health
(speed), how do you know your cure is not worse than no cure? Or not
better?

Alain

@Alain:

Benchmarking your app is fine, but prevention where it makes sense is
really
important.

I see no difference between adding eager-loading, and adding an index

to a table. Do you test the schema for index presence?
When I notice an application is slow, and I see it’s due to a missing
index, I just add the index in a migration, and that’s it. If the
application is still slow, then I add a functional benchmark test, and
I start experimenting.

/puts on DBA hat…

Simply adding an index is a terrible way to improve performance unless
you
know WHY the query is slow. If a developer inadvertently executes 201
sql
queries, exactly how is the addition of an index going to solve that?
The
individual record lookups might be faster but the real problem is the
lack
of left-joins.

By defining indexes you improve database performance by making it faster
to
find and sort the information stored in a table. While indexes speed up
your reads, they can really slow down your inserts and updates. Indexing
is
really a science and it’s not something you just do because “indexes
make my
app run faster.” They can impact a lot of things and an index on one
column
may speed up some queries and slow down others.

Sorry, again, don’t mean to be difficult… I’m enjoying this
conversation
and you have given me much to think about.

I see no difference between adding eager-loading, and adding an index
to a table. Do you test the schema for index presence?
When I notice an application is slow, and I see it’s due to a missing
index, I just add the index in a migration, and that’s it. If the
application is still slow, then I add a functional benchmark test, and
I start experimenting.

Yes, actually I would test the indexes if I had a good way to do it.
Its a shame that testing the DB and schemas isn’t taken more seriously
and easier to do with our tools. I know Glenn Vanderburg has done
talks on testing migrations
(http://glu.ttono.us/articles/2006/06/24/glen-vanderburg-testing-migrations),
and Scott Ambler talks alot about testind and refactoring your db, and
has a book on it as well.

So my lack of testing the schema is more due to a hole in my knowledge
then any lack of will. :slight_smile:

And I have this funny feeling about checking the implementation, and
not the end-result/interface…

I said we test both - low level tests of the association, plus
functional tests for overall speed, plus integration tests.

cheers,
Rob

http://www.ajaxian.com