Module: Shoulda::Macros

Includes:
Private
Included in:
Test::Unit::TestCase
Defined in:
lib/shoulda/macros.rb

Instance Method Summary collapse

Methods included from Private

#get_options!, #model_class

Instance Method Details

#should_change(expression, options = {}) ⇒ Object

Macro that creates a test asserting a change between the return value of an expression that is run before and after the current setup block is run. This is similar to Active Support’s assert_difference assertion, but supports more than just numeric values. See also should_not_change.

Example:

context "Creating a post" do
  setup { Post.create }
  should_change "Post.count", :by => 1
end

As shown in this example, the :by option expects a numeric difference between the before and after values of the expression. You may also specify :from and :to options:

should_change "Post.count", :from => 0, :to => 1
should_change "@post.title", :from => "old", :to => "new"

Combinations of :by, :from, and :to are allowed:

should_change "@post.title"                # => assert the value changed in some way
should_change "@post.title", :from => "old" # => assert the value changed to anything other than "old"
should_change "@post.title", :to   => "new" # => assert the value changed from anything other than "new"


30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/shoulda/macros.rb', line 30

def should_change(expression, options = {})
  by, from, to = get_options!([options], :by, :from, :to)
  stmt = "change #{expression.inspect}"
  stmt << " from #{from.inspect}" if from
  stmt << " to #{to.inspect}" if to
  stmt << " by #{by.inspect}" if by

  expression_eval = lambda { eval(expression) }
  before = lambda { @_before_should_change = expression_eval.bind(self).call }
  should stmt, :before => before do
    old_value = @_before_should_change
    new_value = expression_eval.bind(self).call
    assert_operator from, :===, old_value, "#{expression.inspect} did not originally match #{from.inspect}" if from
    assert_not_equal old_value, new_value, "#{expression.inspect} did not change" unless by == 0
    assert_operator to, :===, new_value, "#{expression.inspect} was not changed to match #{to.inspect}" if to
    assert_equal old_value + by, new_value if by
  end
end

#should_not_change(expression) ⇒ Object

Macro that creates a test asserting no change between the return value of an expression that is run before and after the current setup block is run. This is the logical opposite of should_change.

Example:

context "Updating a post" do
  setup { @post.update_attributes(:title => "new") }
  should_not_change "Post.count"
end


59
60
61
62
63
64
65
66
# File 'lib/shoulda/macros.rb', line 59

def should_not_change(expression)
  expression_eval = lambda { eval(expression) }
  before = lambda { @_before_should_not_change = expression_eval.bind(self).call }
  should "not change #{expression.inspect}", :before => before do
    new_value = expression_eval.bind(self).call
    assert_equal @_before_should_not_change, new_value, "#{expression.inspect} changed"
  end
end