# Unit test fails, but shouldnt have

**URL:** <https://www.ruby-forum.com/t/unit-test-fails-but-shouldnt-have/156128>\
**Category:** Rails\
**Created:** [December 21, 2008, 5:51am UTC](https://www.ruby-forum.com/t/unit-test-fails-but-shouldnt-have/156128 "2008-12-21T05:51:35Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![merrick](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/58956e/32.png) [@merrick](https://www.ruby-forum.com/u/merrick)\
**Post date:** [December 21, 2008, 5:51am UTC](https://www.ruby-forum.com/t/unit-test-fails-but-shouldnt-have/156128/1 "2008-12-21T05:51:35Z")

</div>

Hi,

I have a one to many relationship ( stories & votes ), that i wish to  
test via a unit test. In development everything works great, votes ends  
up w/ the correct story\_id and the relationship is great ( i can  
Vote.find(:last).story or Story.find(:last).votes ) But when I run the  
unit test, it fails. The story gets an id of 996332877 ( which is 10000  
in dev ) and the votes story\_id is 0. Not sure what the heck is going on  
here. Any help would be greatly appreciated.

Merrick

stories:  
±----------------+  
| ID | NAME | URL |  
±----------------+

votes:  
±--------------+  
| ID | STORY\_ID |  
±--------------+

models:

class Story \< ActiveRecord::Base  
validates\_presence\_of :name, :link  
has\_many :votes do  
def latest  
find :all, :order =\> ‘id DESC’, :limit =\> 3  
end  
end  
def to\_param  
“#{id}-#{name.gsub(/\W/, ‘-’).downcase}”  
end  
end

class Vote \< ActiveRecord::Base  
belongs\_to :story  
end

vote test:

test “story\_association” do  
assert\_equal stories(:two), votes(:two).story #FAILS!  
end

---

<div class="post-metadata">

**Author:** ![merrick](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/58956e/32.png) [@merrick](https://www.ruby-forum.com/u/merrick)\
**Post date:** [December 21, 2008, 6:19am UTC](https://www.ruby-forum.com/t/unit-test-fails-but-shouldnt-have/156128/2 "2008-12-21T06:19:42Z")

</div>

Merrick Johnson wrote:

> has\_many :votes do  
> def latest  
> find :all, :order =\> ‘id DESC’, :limit =\> 3  
> end  
> end

Nice! Could someone hint what that syntax does? (But I don’t think it’s  
causing  
the problem…

> vote test:

Next time, write the test first! You should have developed all those  
model-level  
features entirely in test, using the tests essentially the same way - to  
feel  
around and sense changes as you grew the code - as you used your Rails  
app in  
development mode.

But enough of the lecture…

> test “story\_association” do  
> assert\_equal stories(:two), votes(:two).story #FAILS!  
> end

What is in your test/fixtures/stories.yml and votes.yml files?

What does the assert\_equal spew forth when it fails?

–  
Phlip

> **[O'Reilly Media - Technology and Business Training](https://www.oreilly.com)**
>
> Gain technology and business knowledge and hone your skills with learning resources created and curated by O'Reilly's experts: live online training, video, books, our platform has content from 200+ of the world's best publishers.

---

<div class="post-metadata">

**Author:** ![merrick](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/58956e/32.png) [@merrick](https://www.ruby-forum.com/u/merrick)\
**Post date:** [December 21, 2008, 6:21am UTC](https://www.ruby-forum.com/t/unit-test-fails-but-shouldnt-have/156128/3 "2008-12-21T06:21:25Z")

</div>

Good call Philip, turns out my votes.yml fixture looked like this:

one:  
story\_id: one

two:  
story\_id: one

when it should have looked like this:

one:  
story: one

two:  
story: one

Waalaa  
Thanks

---

<div class="post-metadata">

**Author:** ![merrick](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/58956e/32.png) [@merrick](https://www.ruby-forum.com/u/merrick)\
**Post date:** [December 21, 2008, 6:30am UTC](https://www.ruby-forum.com/t/unit-test-fails-but-shouldnt-have/156128/4 "2008-12-21T06:30:18Z")

</div>

Phlip wrote:

> Merrick Johnson wrote:
> 
> > has\_many :votes do  
> > def latest  
> > find :all, :order =\> ‘id DESC’, :limit =\> 3  
> > end  
> > end
> 
> Nice! Could someone hint what that syntax does? (But I don’t think it’s  
> causing  
> the problem…

this creates a method for the resource. in this case it returns the  
newest 3 records. This is pretty helpful because i can call this from a  
view or partial ( @story.votes.latest ) and just get the newest three  
votes. This should work in any DB ( im using Oracle11G )

---

<div class="post-metadata">

**Author:** ![merrick](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/58956e/32.png) [@merrick](https://www.ruby-forum.com/u/merrick)\
**Post date:** [December 21, 2008, 6:50am UTC](https://www.ruby-forum.com/t/unit-test-fails-but-shouldnt-have/156128/5 "2008-12-21T06:50:36Z")

</div>

Phlip wrote:

> Merrick Johnson wrote:
> 
> > this creates a method for the resource. in this case it returns the  
> > newest 3 records.
> 
> Yup!
> 
> > This is pretty helpful because i can call this from a  
> > view or partial ( @story.votes.latest ) and just get the newest three  
> > votes. This should work in any DB ( im using Oracle11G )
> 
> And you never need to say that about MVC or ActiveRecord. The point is  
> you write  
> the minimum code, all in the right places, to support the maximum  
> features. You  
> don’t have to do it the old-fashioned way, with code scattered  
> everywhere, all  
> very similar, getting in the way of each other!
> 
> Now this is why that new aggregation notation is so dang cool. Here’s  
> the Rails  
> 1 way to do a bunch of links:
> 
> class Customer  
> has\_many :accounts  
> has\_many :accounts\_cc, :class\_name =\> ‘Account’,  
> :conditions =\> { :kind =\> ‘cc’ }  
> has\_many :accounts\_ach, :class\_name =\> ‘Account’,  
> :conditions =\> { :kind =\> ‘ach’ }  
> end
> 
> Now compared to raw SQL, has\_many is already an order of magnitude more  
> DRY  
> (Don’t Repeat Yourself). Yet the one requirement to distinguish Credit  
> Card from  
> Checking accounts forces us to create three very wet has\_many calls on  
> the same  
> model. They are, once again, irritatingly similar.
> 
> Here’s the (apparent!) Rails 2 fix:
> 
> class Customer  
> has\_many :accounts do  
> def kind(k)  
> find :all, :conditions =\> { :kind =\> k }  
> end  
> end  
> end
> 
> Boom done. You can write customer.accounts,  
> customer.accounts.kind(‘cc’), and  
> customer.accounts.kind(‘ach’), all very similar to what you could write  
> before,  
> but with far fewer executable lines.
> 
> I’m stoked because we just spent 3 days refactoring a big system which  
> needed  
> this exact fix, and I didn’t know about it. Now I get to install it on  
> Monday.  
> Merry Xmas to me, huh?!
> 
> –  
> Phlip

Just rewrote my test to make a little more sense. The first test fails  
because the order of the votes, if i reverse it it passes. Since I am  
not testing order, the third test ( votes\_association\_improved ) makes a  
little more sense. Is there a way to write that in one statement without  
&& ?

test “votes\_association\_1” do  
assert\_equal [votes(:one), votes(:two)], stories(:one).votes  
#FAILS  
end  
test “votes\_association\_2” do  
assert\_equal [votes(:two), votes(:one)], stories(:one).votes  
#PASSES  
end  
test “votes\_association\_improved” do  
assert stories(:one).votes.include? votes(:one)  
assert stories(:one).votes.include? votes(:two)  
end

---

<div class="post-metadata">

**Author:** ![merrick](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/58956e/32.png) [@merrick](https://www.ruby-forum.com/u/merrick)\
**Post date:** [December 21, 2008, 6:47am UTC](https://www.ruby-forum.com/t/unit-test-fails-but-shouldnt-have/156128/6 "2008-12-21T06:47:10Z")

</div>

Merrick Johnson wrote:

> this creates a method for the resource. in this case it returns the  
> newest 3 records.

Yup!

> This is pretty helpful because i can call this from a  
> view or partial ( @story.votes.latest ) and just get the newest three  
> votes. This should work in any DB ( im using Oracle11G )

And you never need to say that about MVC or ActiveRecord. The point is  
you write  
the minimum code, all in the right places, to support the maximum  
features. You  
don’t have to do it the old-fashioned way, with code scattered  
everywhere, all  
very similar, getting in the way of each other!

Now this is why that new aggregation notation is so dang cool. Here’s  
the Rails  
1 way to do a bunch of links:

class Customer  
has\_many :accounts  
has\_many :accounts\_cc, :class\_name =\> ‘Account’,  
:conditions =\> { :kind =\> ‘cc’ }  
has\_many :accounts\_ach, :class\_name =\> ‘Account’,  
:conditions =\> { :kind =\> ‘ach’ }  
end

Now compared to raw SQL, has\_many is already an order of magnitude more  
DRY  
(Don’t Repeat Yourself). Yet the one requirement to distinguish Credit  
Card from  
Checking accounts forces us to create three very wet has\_many calls on  
the same  
model. They are, once again, irritatingly similar.

Here’s the (apparent!) Rails 2 fix:

class Customer  
has\_many :accounts do  
def kind(k)  
find :all, :conditions =\> { :kind =\> k }  
end  
end  
end

Boom done. You can write customer.accounts,  
customer.accounts.kind(‘cc’), and  
customer.accounts.kind(‘ach’), all very similar to what you could write  
before,  
but with far fewer executable lines.

I’m stoked because we just spent 3 days refactoring a big system which  
needed  
this exact fix, and I didn’t know about it. Now I get to install it on  
Monday.  
Merry Xmas to me, huh?!

–  
Phlip

---

<div class="post-metadata">

**Author:** ![merrick](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/58956e/32.png) [@merrick](https://www.ruby-forum.com/u/merrick)\
**Post date:** [December 21, 2008, 6:32am UTC](https://www.ruby-forum.com/t/unit-test-fails-but-shouldnt-have/156128/7 "2008-12-21T06:32:33Z")

</div>

Merrick Johnson wrote:

> one:  
> story: one
> 
> two:  
> story: one

Ahem. Now for some more lectures!

Your test data fixtures should be literate, so you can document your  
business  
rules in your test cases. In other words, your fixtures should not just  
say “one  
two” etc. They should, instead, tell a … story.

(-:

BTW I guessed what this does:

> has\_many :votes do  
> def latest  
> find :all, :order =\> ‘id DESC’, :limit =\> 3  
> end  
> end

It lets you say a\_story.votes.latest and call that find. I can’t wait to  
use  
that utterly kewl feature!

–  
Phlip

---

<div class="post-metadata">

**Author:** ![merrick](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/58956e/32.png) [@merrick](https://www.ruby-forum.com/u/merrick)\
**Post date:** [December 21, 2008, 7:07am UTC](https://www.ruby-forum.com/t/unit-test-fails-but-shouldnt-have/156128/8 "2008-12-21T07:07:02Z")

</div>

Merrick Johnson wrote:

> test “votes\_association\_improved” do  
> assert stories(:one).votes.include? votes(:one)  
> assert stories(:one).votes.include? votes(:two)  
> end

You need .to\_set, and I will recommend a way to unify assert() and  
assert\_equal() into an assertion that reflects all its variables and  
values when  
it fails.

gem install assert2

require ‘assert2’

assert{ stories(:one).votes.to\_set == votes(:one, :two).to\_set }

.to\_set converts an ordered array into an unordered group, so == can’t  
see the  
order and can’t complain.

(But don’t use assert{ 2.0 } if you use Ruby 1.8.7! A fix for Ruby 1.9  
is in the  
works…)

–  
Phlip

---

<div class="post-metadata">

**Author:** ![merrick](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/58956e/32.png) [@merrick](https://www.ruby-forum.com/u/merrick)\
**Post date:** [December 21, 2008, 7:14am UTC](https://www.ruby-forum.com/t/unit-test-fails-but-shouldnt-have/156128/9 "2008-12-21T07:14:02Z")

</div>

Merrick Johnson wrote:

> ```
> find :all, :order => 'id DESC', :limit => 3
> 
> ```

Note that, in a normal database - and in a unit test that generates new  
records

- the ‘id’ should increment monotonically as new records get added. So  
‘latest’  
is always the highest ‘id’. (Note I have no idea if databases must  
eternally  
enforce this rule, but it stands to reason…)

However, a modern Rails fixture file uses a “magic ‘id’ system” that  
builds  
'id’s out of the hash of each record’s fixture name. So the 'id’s are  
not  
monotonic, and these problems illustrate you ought to use a timestamp,  
such as  
‘created\_at’, instead of an ‘id’, to find the latest records!

This means, instead of using .to\_set in the test, you should actually  
pin down  
the ‘created\_at’ times in your fixture files. And this reminds us,  
again, to use  
the fixtures to tell a little story. Suggest one record is  
“2.hours.ago”, and  
another is “5.minutes.ago”, for example!

–  
Phlip
