[rspec-users] response.body.should be_xml_with -- how to do nested xpath matches

Zach Dennis zach.dennis at gmail.com
Sun Mar 8 15:55:58 EDT 2009

On Sun, Mar 8, 2009 at 2:41 PM, Phlip <phlip2005 at gmail.com> wrote:
> David Chelimsky wrote:
>>>         xpath :'legend[ contains(., "Personal Information") ]' and
>>>         xpath :'label[ contains(., "First name") ]' and
>>>         xpath :input, :type => 'text', :name => 'user[first_name]'
>> This is nice, but the abstractions are operating at different levels.
>> The keyword is "xpath" but the args passed to that look nothing like
>> xpath.
> That's because it's a DSL. You can use raw XPath, XPath with one convenience
> (:'div[ @class = "content" ]' as a symbol implies "any descendant"), or you
> can use an option hash that generates XPath.
> The DSL's benefit is tags like :attribute => foo will automatically escape
> their strings correctly. (That's why the top line of the diagnostic was a
> little cluttered!) foo could contain mixed ' and " payload, and we don't
> care.
>> How about something like:
>> response.body.should be_xml_with do
>>  form :action => '/users' do
>>    fieldset do
>>      legend "Personal Information"
>>      label "First name"
> Because I'm not webrat?
> Yes it would be kewt if label('yo') went into method_missing and came out as
> //label[ contains(., "yo") ]. But I have found that spot checks of
> algorithmic details, such as eRB tags, are more valuable to development than
> slavishly matching your tests to your HTML contents.
> If you write this HTML...
>  <form blah>
>    <input blah>
>    <input blah>
>    <input blah>
>  </form>
> ...and if you test it with a sequence of assertions that exactly match it...
>  page.should contain
>    form blah
>      input blah
>      input blah
>      input blah
>    end
>  end
> ...then you are not really doing TDD. You are merely replicating your code
> as your test, and that will only cause irritation at upgrade time or bug
> time.

This doesn't make a whole lot sense. How does the following move you
from TDD to non-TDD?

   xpath :input, :name => "foo"
   input :name => "foo"

XPath is merely the mechanism in which you're allowed to find
particular elements on a page. After typing:

   xpath :input, :name => "foo"
   xpath :input, :name => "bar"
   xpath :input, :name => "baz"

I would probably write my own wrapper so I could omit the redundant
"xpath" call all over the place. After all, I only care that the input
is found, if it uses XPath to do it--awesome.

> Here's an example from our projects at work:
>    get :thanks_for_purchasing
>    assert_xpath :'center[ . = "Your order has been accepted!" ]'
>    assert_xpath :div, :align => :center do
>      a = assert_xpath(:'p[ contains(., "questions about your membership")
> ]/a')
>      assert{ a.text == a[:href] }
>      assert{ a[:href] == SubscriptionController::CUSTOMER_SERVICE_LINK }
>    end
> Note how much that specifies in the customer acknowledgment page.
>  - the confirmation is centered
>  - the explanation div is centered (yes, we could identify it better!)
>  - part of the explanation div's contents contains "questions..."
>  - next to the "questions..." is an <a>
>  - the <a> contains an href matching its own text contents
>  - the href links to our customer service system

In my experience relying on the syntactic details of the page is
extremely brittle and cumbersome. Writing semantic HTML and semantic
view specs (whether you use rspec or assert2.0 or whatever) seems to
remove unnecessary overhead, such as caring about a "div" or a "p" tag
on the page. Some tags have both syntactic and semantic meaning, such
as forms, labels, fieldsets, and anchor tags.

Given your above assertions, if you replaced your <center> tag (which
is deprecated in HTML 4.01) with a div, and made it centered via CSS,
your assertion would fail. But should it? The presentation is changing
without affecting the behaviour of the view--it's still displaying the
"Your order has been accepted" confirmation. Why not utilize semantic
HTML to not be affected by a syntactic details that doesn't affect
whether or not your view is doing the right thing.

I'd apply the same considerations to the div and the p tags you're
making assertions against.

> I call this topic "XPath can see around corners":
> http://www.oreillynet.com/onlamp/blog/2007/08/xpath_checker_and_assert_xpath.html
> We are using XPath to pin down several elements in a page, allowing the
> other elements to change freely, but forcing them to maintain their
> correlations. That test would fail, for example, if the <a> somehow moved
> away from its introductory paragraph.

Are these correlations best managed by specs? Our customers and
designers move things around on the page all of the time without
affecting behaviour, merely presentation, and having those changes
break all of the view specs is painful. It also seems unnecessary if
they move from a series of "div" tags to a "ul" with "li" elements.

> --
>  Phlip
>  http://www.zeroplayer.com/
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users

Zach Dennis

More information about the rspec-users mailing list