Permalink
Browse files

Changed behavior of "should_not change from" so that it tests the

initial (#from, @expected_before) value *in addition* to testing that
the value did not change at all, instead of merely testing that "it did
not change from this specific initial value".
  • Loading branch information...
1 parent 3c6dbfe commit 5025a56cc7f81645d7efa6d4ff6698c49fe0cf43 Tyler Rick committed Jul 11, 2012
Showing with 71 additions and 8 deletions.
  1. +20 −4 lib/rspec/matchers/built_in/change.rb
  2. +51 −4 spec/rspec/matchers/change_spec.rb
@@ -9,16 +9,28 @@ def initialize(receiver=nil, message=nil, &block)
@eval_before = @eval_after = false
end
- def matches?(event_proc)
- raise_block_syntax_error if block_given?
-
+ def setup_before_matches_or_does_not_match(event_proc)
@actual_before = evaluate_value_proc
event_proc.call
@actual_after = evaluate_value_proc
+ @done_setup = true
+ end
+ def matches?(event_proc)
+ raise_block_syntax_error if block_given?
+ setup_before_matches_or_does_not_match(event_proc) unless @done_setup
+ puts %('#{@expected_before}' actual:'#{@actual_before}')
(!change_expected? || changed?) && matches_before? && matches_after? && matches_expected_delta? && matches_min? && matches_max?
end
+ def does_not_match?(event_proc)
+ raise_block_syntax_error if block_given?
+ setup_before_matches_or_does_not_match(event_proc) unless @done_setup
+
+ return false if !matches_before?
+ !matches?(event_proc)
+ end
+
def raise_block_syntax_error
raise SyntaxError.new(<<-MESSAGE)
block passed to should or should_not change must use {} instead of do/end
@@ -55,7 +67,11 @@ def actual_delta
end
def failure_message_for_should_not
- "#{message} should not have changed, but did change from #{@actual_before.inspect} to #{@actual_after.inspect}"
+ if @eval_before && !expected_matches_actual?(@expected_before, @actual_before)
+ "#{message} should have initially been #{@expected_before.inspect}, but was #{@actual_before.inspect}"
+ else
+ "#{message} should not have changed, but did change from #{@actual_before.inspect} to #{@actual_after.inspect}"
+ end
end
def by(expected_delta)
@@ -481,31 +481,78 @@ def ==(other)
expect { @instance.some_value = "cat" }.to change(@instance, :some_value).from("string").to("cat")
end
- it "fails when #after and #to are different (#from not supplied)" do
+ it "fails when @expected_after and @actual_after are different (#from not supplied)" do
expect do
expect { @instance.some_value = "cat" }.to change(@instance, :some_value).to("dog")
end.to fail_with("some_value should have been changed to \"dog\", but is now \"cat\"")
end
- it "fails when #after and #to are different (#from supplied but matching #before)" do
+ it "fails when @expected_after and @actual_after are different (#from supplied but matching @actual_before)" do
expect do
expect { @instance.some_value = "cat" }.to change(@instance, :some_value).from("string").to("dog")
end.to fail_with("some_value should have been changed to \"dog\", but is now \"cat\"")
end
- it "fails when #before and #from are different (#to not supplied)" do
+ it "fails when @expected_before and @actual_before are different (#to not supplied)" do
expect do
expect { @instance.some_value = "cat" }.to change(@instance, :some_value).from("not_string")
end.to fail_with("some_value should have initially been \"not_string\", but was \"string\"")
end
# The from/before mismatch failure takes precedence over the to/after mismatch
- it "fails when #before and #from are different (#to supplied but not used)" do
+ it "fails when @expected_before and @actual_before are different (#to supplied but not used)" do
expect do
expect { @instance.some_value = "cat" }.to change(@instance, :some_value).from("not_string").to("other")
end.to fail_with("some_value should have initially been \"not_string\", but was \"string\"")
end
end
+describe "should[_not] change(actual, message).from(old).to(new)" do
+ before(:each) do
+ @instance = SomethingExpected.new
+ @instance.some_value = 'initial'
+ end
+
+ it "fails when @expected_before and @actual_before are different (should)" do
+ expect do
+ expect { }.to change(@instance, :some_value).from("other")
+ end.to fail_with("some_value should have initially been \"other\", but was \"initial\"")
+ end
+
+ # #from simply sets an expectation of what the initial value should be before the block is called
+ # so it should behave identically for both should change and should_not change.
+ it "fails when @expected_before and @actual_before are different (should_not)" do
+ expect do
+ expect { }.to_not change(@instance, :some_value).from("other")
+ end.to fail_with(%(some_value should have initially been "other", but was "initial"))
+ end
+
+ # This shows how instead of making the test weaker like the old behavior was, adding a from()
+ # behavior makes the test stronger: it now tests the initial value *in addition* to checking
+ # that the value was not changed at all by the block.
+ it "fails when actual is modified by the block (should_not)" do
+ expect do
+ expect { @instance.some_value = "cat"}.to_not change(@instance, :some_value).from("initial")
+ end.to fail_with(%(some_value should not have changed, but did change from "initial" to "cat"))
+ end
+
+ it "fails when @expected_after and @actual_after are different (should)" do
+ expect do
+ expect { @instance.some_value = "cat" }.to change(@instance, :some_value).to("dog")
+ end.to fail_with(%(some_value should have been changed to "dog", but is now "cat"))
+ end
+
+ it "passes when @expected_after and @actual_after are different (should_not)" do
+ expect { @instance.some_value = "cat" }.to_not change(@instance, :some_value).to("bird")
+ expect { @instance.some_value = "cat" }.to_not change(@instance, :some_value).to("mouse")
+ end
+
+ it "fails when @expected_after and @actual_after are the same (should_not)" do
+ expect do
+ expect { @instance.some_value = "cat" }.to_not change(@instance, :some_value).to("cat")
+ end.to fail_with(%(some_value should not have changed, but did change from "initial" to "cat"))
+ end
+end
+
describe "should change{ block }.from(old).to(new)" do
before(:each) do
@instance = SomethingExpected.new

0 comments on commit 5025a56

Please sign in to comment.