Skip to content

Instantly share code, notes, and snippets.

@alexch
Created July 13, 2010 19:28
Show Gist options
  • Save alexch/474363 to your computer and use it in GitHub Desktop.
Save alexch/474363 to your computer and use it in GitHub Desktop.
class Comparison
@@window = 64
@@prelude = 12
def self.window
@@window
end
def self.window=(val)
@@window = val
end
def self.prelude
@@prelude
end
def self.prelude=(val)
@@prelude = val
end
def initialize(expected, actual)
@expected = expected
@actual = actual
end
def same?
@expected == @actual
end
def different_at
if (@expected.nil? || @actual.nil?)
0
else
i = 0
while (i < @expected.size && i < @actual.size)
if @expected[i] != @actual[i]
break
end
i += 1
end
return i
end
end
def message
"Strings differ at position #{different_at}:\n" +
"expected: #{chunk(@expected)}\n" +
" actual: #{chunk(@actual)}\n"
end
def chunk(s)
prefix, middle, suffix = "...", "", "..."
start = different_at - @@prelude
if start < 0
prefix = ""
start = 0
end
stop = start + @@window
if stop > s.size
suffix = ""
stop = s.size
end
[prefix, s[start...stop].inspect, suffix].join
end
end
if Object.const_defined?(:Spec)
module Spec
module Matchers
class OperatorMatcher
end
class PositiveOperatorMatcher < OperatorMatcher #:nodoc:
def __delegate_operator(actual, operator, expected)
if actual.__send__(operator, expected)
true
elsif expected.is_a?(String) && actual.is_a?(String) && (operator == '==')
fail_with_message Comparison.new(expected, actual).message
elsif ['==', '===', '=~'].include?(operator)
fail_with_message("expected: #{expected.inspect},\n got: #{actual.inspect} (using #{operator})")
else
fail_with_message("expected: #{operator} #{expected.inspect},\n got: #{operator.gsub(/./, ' ')} #{actual.inspect}")
end
end
end
end
end
end
here = File.dirname(__FILE__); require File.expand_path("#{here}/../spec_helper")
describe Comparison do
before do
@old_window = Comparison.window
Comparison.window = 16
@old_prelude = Comparison.prelude
Comparison.prelude = 8
end
after do
Comparison.window = @old_window
end
describe '#same?' do
it "says identical empty strings are the same" do
comparison = Comparison.new("", "")
comparison.same?.should be_true
end
it "says identical non-empty strings are the same" do
comparison = Comparison.new("abc", "abc")
comparison.same?.should be_true
end
it "says two nils are the same" do
comparison = Comparison.new(nil, nil)
comparison.same?.should be_true
end
it "says a string is different from a different string" do
comparison = Comparison.new("abc", "xyz")
comparison.same?.should be_false
end
it "says a string is different from nil" do
comparison = Comparison.new("abc", nil)
comparison.same?.should be_false
end
it "says nil is different from a string" do
comparison = Comparison.new(nil, "abc")
comparison.same?.should be_false
end
end
describe '#different_at' do
describe "returns the location where two strings differ" do
it "at the beginning of the strings" do
Comparison.new("abc", "xyz").different_at.should == 0
end
it "at the middle of the strings" do
Comparison.new("abc", "ayz").different_at.should == 1
end
it "when the expected string is longer" do
Comparison.new("abcd", "abc").different_at.should == 3
end
it "when the actual string is longer" do
Comparison.new("abc", "abcd").different_at.should == 3
end
it "with nil as the expected string" do
Comparison.new(nil, "abc").different_at.should == 0
end
it "with nil as the actual string" do
Comparison.new("abc", nil).different_at.should == 0
end
end
end
describe '#message' do
it 'shows the whole of both strings when the difference is near the start' do
Comparison.new("abc", "xyz").message.should ==
"Strings differ at position 0:\n" +
"expected: \"abc\"\n" +
" actual: \"xyz\"\n"
end
it 'shows ellipses when the difference is in the middle of a long string' do
Comparison.new("abcdefghijklmnopqrstuvwxyz", "abcdefghijkl*nopqrstuvwxyz").message.should ==
"Strings differ at position 12:\n" +
"expected: ...\"efghijklmnopqrst\"...\n" +
" actual: ...\"efghijkl*nopqrst\"...\n"
end
it 'shows ellipses when the difference is near the beginning of a long string' do
Comparison.new("abcdefghijklmnopqrstuvwxyz", "a*cdefghijklmnopqrstuvwxyz").message.should ==
"Strings differ at position 1:\n" +
"expected: \"abcdefghijklmnop\"...\n" +
" actual: \"a*cdefghijklmnop\"...\n"
end
it 'shows ellipses when the difference is near the end of a long string' do
Comparison.new("abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvw*yz").message.should ==
"Strings differ at position 23:\n" +
"expected: ...\"pqrstuvwxyz\"\n" +
" actual: ...\"pqrstuvw*yz\"\n"
end
it 'allows user to override the window size' do
Comparison.window = 10
Comparison.new("abcdefghijklmnopqrstuvwxyz", "a*cdefghijklmnopqrstuvwxyz").message.should ==
"Strings differ at position 1:\n" +
"expected: \"abcdefghij\"...\n" +
" actual: \"a*cdefghij\"...\n"
end
it 'allows user to override the prelude size' do
Comparison.prelude = 2
Comparison.new("abcdefghijklmnopqrstuvwxyz", "abcdefghijkl*nopqrstuvwxyz").message.should ==
"Strings differ at position 12:\n" +
"expected: ...\"klmnopqrstuvwxyz\"...\n" +
" actual: ...\"kl*nopqrstuvwxyz\"...\n"
end
end
it "overrides RSpec's == matcher for strings" do
lambda do
"xyz".should == "abc"
end.should raise_error(Spec::Expectations::ExpectationNotMetError, Comparison.new("abc", "xyz").message)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment