Unit test problem with time update


#1

Hi all, I am new to Ruby on Rails and struggling to finish my class
project.
I have problem with unit testing, if any body could help.

I have a function that updates ‘feeds’ table. It has a columns: id,
feeddata, lastupdate. feedupdate.

The function in method feed.rb is as follows:

def Feed.updatefeed(feed_id)
@u = Feed.find(feed_id)
#response=fetch(@u.sourcelink)
#@u.feeddata=response.body
@u.lastupdate=Time.now
@u.save!
end

my test feed_test.rb is as follows:

require File.dirname(FILE) + ‘/…/test_helper’

class FeedTest < ActiveSupport::TestCase

Replace this with your real tests.

fixtures :feeds

def test_truth
assert true
end

def test_updatefeed
feed1 = Feed.find(:first,:conditions=>[“id=?”,12])
Feed.updatefeed(feed1.id)
assert_equal(Time.now, feed1.lastupdate)
end

end

fixture:

feed_1:
id: 1
sourcelink: http://sports.yahoo.com/ncaaf/teams/aad/ical.ics
feeddata: testdata
lastupdate: 2009-02-17 22:42:25
used: 1

feed_12:
id: 12
sourcelink: http://icalx.com/public/wesleyrhall/Astronomy.ics
feeddata: testdata
lastupdate: 2009-02-17 22:42:25
used: 1

My ‘updatefeed’ function is working on application well. But my test
doesn’t show the updated ‘lastupdated’ column date but only the value in
fixture. Shouldn’t the fixture value be updated on execution and after
comparison set it back?


#2

On Apr 11, 11:43 pm, Ps_gem Sh_gem removed_email_address@domain.invalid
wrote:

My ‘updatefeed’ function is working on application well. But my test
doesn’t show the updated ‘lastupdated’ column date but only the value in
fixture. Shouldn’t the fixture value be updated on execution and after
comparison set it back?

If you do SomeMode.find(123) twice, you’ll get back two separate
objects (that both correspond to the row in the database with id 123.

The way you’ve written your code, the updatefeed method loads a
separate copy of the feed and updates that, but you do your assertion
on a separate copy of it. You would need to reload it to see the
change you made. It’s also a bit odd that you’ve made updatefeed a
class method - looks much more like an instance method to me - you
also probably don’t want to be using an instance variable in there.
Lastly, if you table has an updated_at column, rails will fill that in
for you everytime you save the object.

Fred


#3

Ps_gem Sh_gem wrote:

Hi all, I am new to Ruby on Rails and struggling to finish my class
project.
I have problem with unit testing, if any body could help.

Professor Phlip will now dispense some tips.

I have a function that updates ‘feeds’ table. It has a columns: id,
feeddata, lastupdate. feedupdate.

Don’t dupe the name of feeds into the feeds fields - feeddata should be
data.
And reconsider ‘data’ - what is the intent of its variable? Where will
it come
out into the world and do something?

Next, “script/generate model” will generate created_on and updated_on
automatically for you. Maybe they are already there; and maybe this
assignment
intends to see if you will use them.

The function in method feed.rb is as follows:

def Feed.updatefeed(feed_id)

update_feed. The goal is to match natural language whenever possible, so
break
words up with underbars.

 @u = Feed.find(feed_id)

I don’t think you will use @u with the same value in any other method
(also, you
are in a class method, so the @u lives in essentially the metaclass of
the Feed
class, or something like that). Call it ‘feed’.

 #response=fetch(@u.sourcelink)
 #@u.feeddata=response.body

Put spaces around binary operators like =.

 @u.lastupdate = Time.now
 @u.save!

end

my test feed_test.rb is as follows:

class FeedTest < ActiveSupport::TestCase

Replace this with your real tests.

Please delete all code that is not useful - including that comment, and
including the test_truth stub.

fixtures :feeds

def test_truth
assert true
end

def test_updatefeed
feed1 = Feed.find(:first,:conditions=>[“id=?”,12])
Feed.updatefeed(feed1.id)
assert_equal(Time.now, feed1.lastupdate)

After you .reload the feed1, you will discover you cannot compare floats
for
equality. A time is a float, and the time will increment by a
microsecond or so
after the “money line” fires.

Try this:

   feed = feeds(feed_1)
   feed.update_attribute :updated_at, 1.hour.ago # spike
   Feed.update_feed(feed.id)
   feed.reload
   assert 1.second.ago < feed.updated_on &&
             feed.updated_on < 1.second.from_now

Note I dropped the (). That is to rub the nose of every Java user how
easy Ruby
makes unit tests, especially assertions.

My assertion is a variation on a common theme - assert_close, or
assert_in_delta. The point is to ensure a floating point number falls
inside a
tiny range; larger than common software math rounding errors, and larger
than
the time one test takes to execute. It still uses wall-clock time, not
CPU time,
so if your CPUs were loaded down with work the assertion might fail, but
tests
typically have the computer to themselves so we won’t worry about that.

end

end

feed_1:
id: 1

If your Rails version is > 2.0.0, drop the id: 1, and use automatically
generated ids.

sourcelink: http://sports.yahoo.com/ncaaf/teams/aad/ical.ics

If the feed deals with yahoo, don’t name it :feed_1. Name it :yahoo


Phlip


#4

http://sports.yahoo.com/ncaaf/teams/aad/ical.ics was just an example of
a link to download iCalendar feed, it can be from anywhere so I used
feed_1, feed_2…feed_n for generic term.

This worked:

def test_updatefeed
feed = feeds(:feed_1)
feed.update_attribute :lastupdate, 1.hour.ago # spike
Feed.updatefeed(feed.id)
feed.reload
assert 1.second.ago < feed.lastupdate &&
feed.lastupdate < 1.second.from_now
end

Thanks