Module: AssertDifference

Defined in:
lib/assert_difference/version.rb,
lib/assert_difference.rb

Overview

Copyright © 2010, 2011, 2012, 2014 José Pablo Fernández

Constant Summary collapse

VERSION =
"1.0.0"

Instance Method Summary collapse

Instance Method Details

#assert_difference(expectations, expected_difference = 1, message = nil, &block) ⇒ Object

Test numeric difference between the return value of an expression as a result of what is evaluated in the yielded block.

assert_difference "Article.count" do
  post :create, :article => {...}
end

An arbitrary expression is passed in and evaluated.

assert_difference "assigns(:article).comments(:reload).size" do
  post :create, :comment => {...}
end

An arbitrary positive or negative difference can be specified. The default is +1.

assert_difference "Article.count", -1 do
  post :delete, :id => ...
end

An array of expressions can also be passed in and evaluated.

assert_difference [ "Article.count", "Post.count" ], +2 do
  post :create, :article => {...}
end

A error message can be specified.

assert_difference "Article.count", -1, "An Article should be destroyed" do
  post :delete, :id => ...
end

Various assertions can be combined into one, instead of writing:

assert_difference "Company.count" do
  assert_difference "User.count", +5 do
    assert_difference "Article.count", -1 do
      post :something
    end
  end
end

you can now write:

assert_difference "Article.count" => 1, "assigns(:article).comments(:reload).size" => 1, "Article.count" => -1 do
  post :something
end

the results of the block is the result of the assert, so you can write

email = assert_difference "ActionMailer::Base.deliveries.count" => +1 do
    Mailer.reset_password_email(@user).deliver
end
assert_equal [@user.email], email.to

the expectations can also be ranges, for example:

assert_difference "Article.count" => 1, "sample_coments.count" => 2..4 do
  post :something
end

Parameters:

  • expectations (Array, Hash)

    array of expectations to evaluate or hash table of expectations and expected difference.

  • expected_difference (Integer or Range) (defaults to: 1)

    expected difference when using an array or single expression.

  • message (String, nil) (defaults to: nil)

    error message to display on top of the description of the expectation failed.

Returns:

  • Object whatever the block returned



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/assert_difference.rb', line 72

def assert_difference(expectations, expected_difference = 1, message = nil, &block)
  binding = block.send(:binding)
  expectations = expectations_as_hash(expected_difference, expectations) unless expectations.is_a? Hash
  before = expectations.keys.each_with_object({}) { |expression, before| before[expression] = eval(expression, binding) }

  result = yield

  after = expectations.keys.each_with_object({}) { |expression, after| after[expression] = eval(expression, binding) }
  error_messages = generate_error_messages(after, before, expectations, message)
  if error_messages.any?
    fail error_messages.join("\n\n").strip
  end

  return result
end