[rspec-users] how to write nested XPath matchers

David Chelimsky dchelimsky at gmail.com
Mon Feb 16 10:55:08 EST 2009


On Mon, Feb 16, 2009 at 9:36 AM, Phlip <phlip2005 at gmail.com> wrote:
>> This looks pretty cool. I wonder if you'd have any interest in making
>> this a bit more rspec-friendly? Something like an option to run it
>> like this:
>
> Here's the spec. The sauce is below my signature.
>
>  it 'should have a user form with the first name' do
>    render '/users/new'
>    response.body.should be_xml_with do
>      xpath :form, :action => '/users' do
>        xpath :fieldset do
>          xpath :'legend[ contains(., "Personal Information") ]' and
>          xpath :'label[ contains(., "First name") ]' and
>          xpath :input, :type => 'text', :name => 'user[first_name]'
>        end
>      end
>    end
>  end
>
> Now, two issues. Firstly, what is the point of writing verbiage, designed
> for review by the customer team, if they should not be expected to
> understand hardcore engineering gibberish beginning with "body.should
> be_xml_with do"? A sentence that is only partly English does more harm than
> good!

When RSpec is used as customer facing, they see the docstrings
(strings passed to describe() and it()), not the internal code. That's
for developers.

> Secondly, when an xpath() fails, it prepares an elaborate and detailed
> analysis of the entire situation, packs this into a flunk(), and raises it
> in a Test::Unit::AssertionFailedError.
>
> Then RSpec then throws all that stuff away, and provides an incorrect stack
> trace to an internal error. Switching my 'user[first_name]' to
> 'user[first_nome]' provides this:
>
> NoMethodError in '/users/new should have xpathic tags'
> You have a nil object when you didn't expect it!
> You might have expected an instance of Array.
> The error occurred while evaluating nil.first
> ./spec/views/users/new.html.erb_spec.rb:50:
>
> So if I were to rescue my own AssertionFailedError, and pack it into a
> failure_message, wouldn't that effort be redundant?

Take a look at http://github.com/dchelimsky/rspec/blob/f6c75b1417d9178d4dcaaf9e892e23474d340ff6/lib/spec/matchers/wrap_expectation.rb,
I think it'll solve this problem.

HTH,
David

>
> --
>  Phlip
>
> require 'assert2/xpath'
>
> Spec::Runner.configure do |c|
>  c.include Test::Unit::Assertions
> end  #  TODO blog this
>
>  class BeXmlWith
>
>    def initialize(scope, &block)
>      @scope, @block = scope, block
>    end
>
>    def matches?(stwing, &block)
>      waz_xdoc = @xdoc
>      @block = block if block
>      @scope.assert_xhtml stwing
>      return (block || @block || proc{}).call
>    ensure
>      @xdoc = waz_xdoc
>    end
>
>    def failure_message
>      "yack yack yack"
>    end
>
>    def negative_failure_message
>      "yack yack yack"
>    end
>  end
>
>  def be_xml_with(&block)
>    BeXmlWith.new(self, &block)
>  end
>
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>


More information about the rspec-users mailing list