Interesting Things
In exploring options for RSpec testing of XML responses, one project decided a custom XPath matcher would do the trick nicely:
items = Item.find(:all) get :index response.body.should have_nodes("//items/item", items.size) response.body.should have_xpath("//items/item[ position() = 1 and @id = '0001' ]") response.body.should_not have_xpath("//bogus")Some other possibilities:
Hashes...
items = Item.find(:all) get :index hash = Hash.from_xml(response.body) hash['ancestor']['parent']['items']['item'].size.should == items.size hash['ancestor']['parent']['items']['item'][0]['id'].should == '0001' hash['ancestor']['parent']['bogus'].should be_nilHpricot...
items = Item.find(:all) get :index doc = Hpricot(response.body) doc.search("//items/item").size.should == items.size doc.at("//items/item[ @id = '0001' ]").position.should == 1 doc.at("//bogus").should be_nilassert_select from Rail's Test::Unit (using CSS-style selectors)...
items = Item.find(:all) get :index assert_select("items > item", :count => 5) assert_select("items > item:nth-child(1)[id=?]", '0001') assert_select("bogus", false)
What are your favorite techniques for asserting XML/XPath?
Something to consider when test-driving controller code:
You're working with
ActionController::TestResponse. So,response.success?,response.redirect?, etc. are available for you there (since they are defined on TestResponse), but not in your actual controllers. That is, things blow up if you try to use@response.success?in your application,e.g. to determine whether or not to store the current URL and redirect there after a login.








I always use ruby more for applications. I've read somewhere that they're coming up with a more advanced and stable version of it. Any thoughts?
remove
We use a custom XPath matcher, based on the link you provided, using Hpricot to do the parsing. I found a decent speed improvement by using Hpricot instead of REXML. Also, if you are considering assert_select, but want to use RSpec, then why wouldn't you use have_tag, it's just a wrapper around assert_select.
remove
@James - Great feedback. We actually also have at least one project using custom matchers backed by Hpricot, but they're less complete (and less publicly accessible) than the one linked above. Good suggestion with Rspec's
have_tag; example set ported tohave_tagbelow. Keep in mind that you take a performance hit when usinghave_tag(and by extensionassert_select) since Rails loads the entire DOM.remove
And, I guess this would be nicer for that last one...
response.should_not have_tag("bogus")remove