Validating RSS Feeds with RSpec
Posted by Rick DeNatale Fri, 08 Feb 2008 15:38:00 GMT
One of my current Rails projects involves generating an RSS feed. While I was working on this the other night, it seemed to be working, so I deployed it to the staging server. Everything looked fine. If I fetched it with Firefox, the browser offered to let me subscribe to the feed with Google Reader, and if I used Safari I'd see a nice view of the feed just like I expected.
So I sent a note via our campfire to check it out, and a colleague replied that his Safari was saying that it was in an invalid format.
So I went to the W3 RSS Feed Validation Service and worked through the validation issues, after which his browser was as happy as mine.
Of course, having been through that, I wanted to make sure that RSS validation was covered in the specs for the project.
I went looking for an existing RSpec matcher, and found a matcher to validate XHTML but nothing for RSS.
I then found the feedvalidator gem which provides a Ruby interface to the SOAP interface to the W3 feed validator. You would think that W3 would be providing a REST interface! The gem already provides assertions for use with Test::Unit, so I just built an RSpec matcher.
class BeValidFeed
require 'feed_validator'
require 'tmpdir'
require 'md5'
def matches?(response)
return true if validity_checks_disabled?
v = W3C::FeedValidator.new()
fragment = response.body
filename = File.join Dir::tmpdir, 'feed.' + MD5.md5(fragment).to_s
begin
response = File.open filename do |f| Marshal.load(f) end
v.parse(response)
rescue
unless v.validate_data(fragment)
@failure = " could not access w3 validator to validate the feed."
return false
end
File.open filename, 'w+' do |f| Marshal.dump v.response, f end
end
v.valid?
end
def description
"be valid xhtml"
end
def failure_message
@failure || " expected xhtml to be valid, but validation produced these errors:\n #{@message}"
end
def negative_failure_message
" expected to not be valid, but was (missing validation?)"
end
private
def validity_checks_disabled?
ENV["NONET"] == 'true'
end
end
def be_valid_feed
BeValidFeed.new
end I saved this as spec/be_valid_feed.rb
And in a view or controller spec, I can include this file, and test a response with:
response.should be_valid_feed If you use this in a controller spec, you will need to tell RSpec to integrate_views, or you won't have much of a feed to check. If you use nested example groups, integrate_views needs to be inside the inner group.









