views:

84

answers:

2

When I learned about proxy_options I started using it to test all my named scopes. But then I found myself simply copying the conditions hash straight from the model, so it wasn't really testing the correctness of the results:

  po = {:conditions => "foo.created_at <= '#{Time.now.beginning_of_week}'"}
  assert_equal po, Foo.created_this_week

Another approach is to come up with positive and negative examples and see if they are included in the results or not:

  this_week = Foo.make(:created_at => Time.now)
  last_week = Foo.make(:created_at => 1.week.ago)
  assert Foo.created_this_week.include?(this_week)
  assert !Foo.created_this_week.include?(last_week)

But this doesn't do a good job of checking the boundaries and when things get more complicated you'll have a whole long list of assert includes?. It seems it would be nicer to come up with an expected set of results and then just check to make sure it matches:

  Foo.make(:created_at => 1.week.ago)
  results = [Foo.make(:created_at => Time.now)]
  assert_equal results, Foo.created_this_week

But then the test might fail if the results are returned in a different order than you supplied. I guess you could implement <=> in your model so you could sort both arrays. But it seems like that shouldn't really be neccessary. Is there a better way to test these kinds of search methods? Or at least a generally accepted right way?

+1  A: 

I would suggest checking out this thoughtbot blog post discussing just this topic:

http://robots.thoughtbot.com/post/200254501/testing-named-scopes

jonnii
Thanks for the link. It looks like his answer is to 1) make named scopes private so you don't have to test them and 2) use the array equality method to test search methods and ignore the ordering brittleness.
eremite
That's pretty much the gist of it. Does that help at all?
jonnii
A: 

I think I've come to the conclusion that there is no "generally accepted right way" to do this.

I guess my personal solution will be to stop testing simple named_scopes and use the assert includes? method for testing more complicated search functionality.

eremite