[rspec-devel] slightly-less-simple-matcher [was: crazy semantic question]
David Chelimsky
dchelimsky at gmail.com
Sun Jun 22 19:31:53 EDT 2008
The ??? of the expression "x should y" is positive.
The ??? of the expression "x should not y" is negative.
So we've got:
sense
outcome
consequence
mood
feeling
aura
timbre
(un)likeliness
(un)likelihood
Let me provide a bit more context. RSpec matchers don't know whether
they're being called with should or should_not. I'm toying with adding
that capability such that if the matcher will accept a 2nd argument to
the matches? method it will be given a hash. Then you can do this:
def matches?(given, options, &block)
if options[:should_ness] == :positive
# handle the 'should' case
else
# handle the 'should_not' case
end
end
Although, now that I'm looking at it, it could just be:
def matches?(given, options, &block)
if options[:called_with] == :should
# handle the 'should' case
else
# handle the 'should_not' case
end
end
Maybe that solves the problem? Thoughts?
For those interested, this stems from some evolution of the
simple_matcher method. Right now (in git) you can do this:
def report_to(manager)
simple_matcher do |employee, matcher|
matcher.failure_message = "expected #{employee} to report to
#{manager}"
employee.reports_to?(manager)
end
end
Some have expressed a desire to make these more like expectation
wrappers, where you can put a couple of logical expectations together.
The example above uses a boolean expression. But what if you wanted to
do this?
def report_to(manager)
simple_matcher do |employee, matcher|
matcher.failure_message = "expected #{employee} to report to
#{manager} and #{manager} not to report to #{employee}"
employee.reports_to?(manager).should be_true
manager.reports_to?(employee).should be_false
end
end
This actually works ... as long as you only call it with should. If
you use should_not, you'll get the wrong response, whereas the
original boolean expression would work fine.
To be able to support this, the matcher *could* be written like this:
def report_to(manager)
simple_matcher do |employee, matcher|
if matcher.called_with_should?
matcher.failure_message = "expected #{employee} to report to
#{manager}"
employee.reports_to?(manager).should be_true
manager.reports_to?(employee).should be_false
else
matcher.failure_message = "expected #{employee} to report to
#{manager} and #{manager} not to report to #{employee}"
employee.reports_to?(manager).should be_false
end
end
end
Now you have a custom matcher that can handle should and should_not
cases with the appropriate expectations and semantics for each. A bit
more complex than maybe a simple matcher should be :) And certainly
not necessary for you to use this way - just available.
Any feedback on this is welcome.
Cheers,
David
More information about the rspec-devel
mailing list