Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Make eq and eql matchers diffable and clean up when to/not diff
  • Loading branch information
dchelimsky committed Sep 4, 2010
1 parent 04eeba1 commit e7303e9
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 20 deletions.
60 changes: 60 additions & 0 deletions features/expectations/diffing.feature
@@ -0,0 +1,60 @@
Feature: diffing

When appropriate, failure messages will automatically include a diff.

Scenario: diff for a multiline string
Given a file named "example_spec.rb" with:
"""
describe "a multiline string" do
it "is like another string" do
expected = <<-EXPECTED
this is the
expected
string
EXPECTED
actual = <<-ACTUAL
this is the
actual
string
ACTUAL
actual.should eq(expected)
end
end
"""
When I run "rspec example_spec.rb"
Then the output should contain:
"""
Diff:
@@ -1,4 +1,4 @@
this is the
- expected
+ actual
string
# ./example_spec.rb:13
"""

Scenario: no diff for a single line strings
Given a file named "example_spec.rb" with:
"""
describe "a single line string" do
it "is like another string" do
expected = "this string"
actual = "that string"
actual.should eq(expected)
end
end
"""
When I run "rspec example_spec.rb"
Then the output should not contain "Diff:"

Scenario: no diff for numbers
Given a file named "example_spec.rb" with:
"""
describe "a number" do
it "is like another number" do
1.should eq(2)
end
end
"""
When I run "rspec example_spec.rb"
Then the output should not contain "Diff:"
6 changes: 5 additions & 1 deletion lib/rspec/expectations/fail_with.rb
Expand Up @@ -21,7 +21,7 @@ def fail_with(message, expected=nil, actual=nil) # :nodoc:
if any_multiline_strings?(actual, expected)
message << "\nDiff:" << self.differ.diff_as_string(actual, expected)
end
elsif no_procs?(actual, expected)
elsif no_procs?(actual, expected) && no_numbers?(actual, expected)
message << "\nDiff:" << self.differ.diff_as_object(actual, expected)
end
end
Expand All @@ -42,6 +42,10 @@ def all_strings?(*args)
def any_multiline_strings?(*args)
all_strings?(*args) && args.any? {|a| a =~ /\n/}
end

def no_numbers?(*args)
args.none? {|a| Numeric === a}
end
end
end
end
3 changes: 3 additions & 0 deletions lib/rspec/matchers/eq.rb
Expand Up @@ -14,6 +14,9 @@ module Matchers
# 5.should_not eq(3)
def eq(expected)
Matcher.new :eq, expected do |_expected_|

diffable

match do |actual|
actual == _expected_
end
Expand Down
3 changes: 3 additions & 0 deletions lib/rspec/matchers/eql.rb
Expand Up @@ -14,6 +14,9 @@ module Matchers
# 5.should_not eql(3)
def eql(expected)
Matcher.new :eql, expected do |_expected_|

diffable

match do |actual|
actual.eql?(_expected_)
end
Expand Down
65 changes: 46 additions & 19 deletions spec/rspec/expectations/fail_with_spec.rb
Expand Up @@ -6,35 +6,62 @@
before(:each) do
RSpec::Expectations.stub(:differ) { differ }
end


it "calls differ if expected/actual are not strings (or numbers or procs)" do
differ.should_receive(:diff_as_object).and_return("diff")
lambda {
RSpec::Expectations.fail_with "the message", Object.new, Object.new
}.should fail_with("the message\nDiff:diff")
end

context "with two strings" do
context "and actual is multiline" do
it "calls differ" do
differ.should_receive(:diff_as_string).and_return("diff")
lambda {
RSpec::Expectations.fail_with "the message", "expected\nthis", "actual"
}.should fail_with("the message\nDiff:diff")
end
end

context "and expected is multiline" do
it "calls differ" do
differ.should_receive(:diff_as_string).and_return("diff")
lambda {
RSpec::Expectations.fail_with "the message", "expected", "actual\nthat"
}.should fail_with("the message\nDiff:diff")
end
end

context "and both are single line strings" do
it "does not call differ" do
differ.should_not_receive(:diff_as_string)
lambda {
RSpec::Expectations.fail_with("the message", "expected", "actual")
}.should fail_with("the message")
end
end
end

it "does not call differ if no expected/actual" do
lambda {
RSpec::Expectations.fail_with "the message"
}.should fail_with("the message")
end

it "calls differ if expected/actual are presented separately" do
differ.should_receive(:diff_as_string).and_return("diff")

it "does not call differ expected is Numeric" do
lambda {
RSpec::Expectations.fail_with "the message", "expected\nthis", "actual"
}.should fail_with("the message\nDiff:diff")
end

it "does not call differ if expected/actual are single line strings" do
differ.should_not_receive(:diff_as_string)
RSpec::Expectations.fail_with("the message", "expected", "actual") rescue nil
RSpec::Expectations.fail_with "the message", 1, "1"
}.should fail_with("the message")
end

it "calls differ if expected/actual are not strings" do
differ.should_receive(:diff_as_object).and_return("diff")

it "does not call differ when actual is Numeric" do
lambda {
RSpec::Expectations.fail_with "the message", Object.new, Object.new
}.should fail_with("the message\nDiff:diff")
RSpec::Expectations.fail_with "the message", "1", 1
}.should fail_with("the message")
end

it "does not call differ if expected or actual are procs" do
differ.should_not_receive(:diff_as_string)
differ.should_not_receive(:diff_as_object)
lambda {
RSpec::Expectations.fail_with "the message", lambda {}, lambda {}
}.should fail_with("the message")
Expand Down
4 changes: 4 additions & 0 deletions spec/rspec/matchers/eq_spec.rb
Expand Up @@ -3,6 +3,10 @@
module RSpec
module Matchers
describe "eq" do
it "is diffable" do
eq(1).should be_diffable
end

it "matches when actual == expected" do
1.should eq(1)
end
Expand Down
4 changes: 4 additions & 0 deletions spec/rspec/matchers/eql_spec.rb
Expand Up @@ -3,6 +3,10 @@
module RSpec
module Matchers
describe "eql" do
it "is diffable" do
eql(1).should be_diffable
end

it "matches when actual.eql?(expected)" do
1.should eql(1)
end
Expand Down

0 comments on commit e7303e9

Please sign in to comment.