[rspec-users] customize description and failure messages when writing rspec matcher dsl

Anran Yang 08to09 at gmail.com
Thu Nov 24 01:48:49 EST 2011


Dear all,

I recently tried to write a custom matcher using rspec dsl, which I'd like
to use as the following:

==========hpgc_spec.rb===================

require "spec_helper"

describe Hpgc do
  specify do
    should be_structured_as(
    { :app => {
        :has => [
            :name,
            :author,
            :org,
            :version,
            :abstract,
            :uri
        ],

        :can_be_a => {
            :dataset => {
                :can_be_a => {
                    :vector => {},
                    :raster => {}
                }
            },

            :program => {
                :has => [
                    :language,
                    :parallel_programming_model,
                    :parallel_performance_overview,
                    :category
                ]
            }
        },

        :has_many => {
            :app_option => {
                :has => [
                    :switch,
                    :description
                ]
            },

            :app_io => {
                :has => [
                    :name,
                    :description,
                    :is_in
                ]
            }
        }
    }})
  end
end

===========================================

The purpose is to test the entire model structure(attributes, inheritance
and association). Then I wrote following code to implement it:

========be_structured_as.rb===================


# This is a matcher for test hpgc model structure

RSpec::Matchers.define :be_structured_as do |structure|
  def check(namespace, klass, desc)
    (desc[:has_many] ||= {}).keys.each { |item|
klass.to_s.camelize.constantize.new.should have_many
item.to_s.pluralize.to_sym }
    if !desc[:can_be_a] || desc[:can_be_a].empty?
      obj = Factory.create(klass)
      obj.should have_these_attributes (desc[:has] ||= [])
    else
      desc[:can_be_a].keys.map { |sub| sub.to_s }.should ==
namespace.subclasses_of(klass.to_s)
      desc[:can_be_a].each { |key, value| check namespace, key, value }
    end
  end

  match do |namespace|
    self.class.send :include, namespace
    structure.each { |key, value| check namespace, key, value }
  end
end

===============================================

To simplify the matcher definition,  I used some other machers like
"obj.should have_these_attributes (desc[:has] ||= [])", this works fine,
thanks to the excellent new matcher dsl syntax. Howerver, I got trouble
when running the test using "rspec spec/models/hpgc_spec.rb -fd". The test
passed but print

[image: Screenshot.png]

instead of something like "Hpgc should be structured as ...". I think it
may due to the other matcher I used because the message is from the matcher
"have_these_attributes". I try to add method "description" but seems it
doesn't work.

And the failure message is also a problem. I search the web and come across
some solutions, but all of them need manually build the message. I've not
come out a clean way to do this(I must add some invasive clauses to track
the error) and think maybe the best behaviour would be that it "throw" the
failure message of inner matchers or false-value expressions. But this time
it just  told me something like "Hpgc is expected to be structured as ...".

Any idea?

Best Regards,

YANG Anran
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20111124/ceb96a59/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: image/png
Size: 5244 bytes
Desc: not available
URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20111124/ceb96a59/attachment-0001.png>


More information about the rspec-users mailing list