On 27 May 2008, at 12:44, andypearson wrote:
def self.cache_all
feeds = self.find(:all)
for feed in feeds
xml = REXML::Document.new Net::HTTP.get(URI.parse(feed.url))
xml.elements.each '//item' do |item|
Item.prepare_and_save(feed, item)
end
end
end
Problems are now beginning to arise when trying to write the specs
for this
method. I started from scratch slowly building up the specs but it
has led
to an awful amount of mocks and stubs, and I am not even sure
whether they
are asking the correct things of the method.
Can anyone give me some pointers on how to write useful, meaningful
specs
for this method?
Hi Andy
I think the problem comes from two things - trying to specify the
details of an algorithm instead of checking it transforms the data
correctly, and having too much logic in a class method.
To take some Feed-specific logic out, try making an accessor method,
such as Feed#uri (I can't think of a good name for it), then you could
replace one line with this:
xml = REXML::Document.new = Net::HTTP.get(feed.uri)
Alternatively, go one step further and have a method in Feed that does
the Net::HTTP.get, so you could write this:
xml = feed.xml_source
Obviously you will still need the corresponding specs in the Feed
instance methods, but at least you've encapsulated the logic related
to fetching the URI/XML.
The other thing is the "item" elements. I don't know what
xml.elements.each yields, but I'm guessing it's either plain text
(XML) or some REXML object. If it's plain XML fine, but if it's an
REXML object, you don't want your code depending on that (you're tying
yourself down to a specific library). Instead, consider parsing the
XML in Feed.cache_all. I'm imagining something like this:
feed.prepare_and_save_item(:item_attr_1 => "foo",
:item_attr_2 => "bar",
...)
The other thing I have found is that I seem to have incorrectly
stubbed
xml.elements.each meaning that the contents of the block are never
called,
how should I be specifying this behavior?
Just noticed that Tom replied and pointed out the issue. But if you
refactor the code like I describe above, you can avoid the issue.
Just stub feed.xml_source (or whatever) to return some sample valid
feed XML, and check that Feed.cache_all correctly extracts the item
data.
I can't say that my way is better or worse than the way you are going
about it. But I (where possible) I always test the output of third-
party libraries rather than my use of them. It avoids loads of stubs
that don't, in any case, prove you're using the library correctly so
you can see immediately if your code is likely to work in the wild.
Hope this helps
Ashley
--
http://www.patchspace.co.uk/
http://aviewfromafar.net/
_______________________________________________
rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users