Apr 26 2009
∞
cucumber negative expectations
*update* I forgot to include matcher block arguments… code is fixed below
A ton of my Then step definitions have this pattern:
Then %r{should( not)? be happy$} do |should_not|
# ...
end
Dealing with the conditional should or should not got annoying, and I thought about some hardcore solutions (seen in this LH ticket)… but I ended up with a simpler solution with Andrew Vit’s help:
require 'singleton'
module NegativeExpectationsHelper
class State
include Singleton
def is_negative?
@negative === true
end
def is_negative!
@negative = true
end
def restore!
@negative = false
end
end
module ObjectExpectations
def self.included(base)
base.class_eval do
alias_method :original_should, :should
alias_method :original_should_not, :should_not
def should(*args, &block)
should_if_true(!State.instance.is_negative?, *args, &block)
end
def should_not(*args, &block)
should_if_true(State.instance.is_negative?, *args, &block)
end
end
end
private
def should_if_true(cond, *args, &block)
cond ? self.send(:original_should, *args, &block) : self.send(:original_should_not, *args, &block)
end
end
def negative_expectations_if(cond)
raise "expected block" unless block_given?
State.instance.is_negative! if cond
yield
State.instance.restore! if cond
end
end
class Object
include NegativeExpectationsHelper::ObjectExpectations
end
World(NegativeExpectationsHelper)
That’s probably cumbersome (whoa, I just made a typo, “cucumbersome” and thought it would make for a nice cucumber inside joke) since I’m a little bit of a ruby meta-programming n00b. But anyway, now I can do:
Then %r{should( not)? be happy$} do |should_not|
negative_expectations_if(should_not) do
should be_happy
end
end