assert_not_diff

The output of Ruby's Test::Unit::TestCase's
assert_equal(expected, actual) when expected and actual are not the same is often not as useful as it could be. For example:
expected = [1,99,2,3,{:a=>34,:b=>43}]
actual = [1,2,3,4,{:a=>324,:c=>555,:b=>43},5]
assert_equal expected, actual
produces:
<[1, 99, 2, 3, {:a=>34, :b=>43}]> expected but was
<[1, 2, 3, 4, {:a=>324, :c=>555, :b=>43}, 5]>.
For large objects which differ only slightly the output that tells you where they differ quickly gets lost in the mass of output telling you where they don't.

Perhaps what's happened here is a sort of Primitive Obsession.
It's as though assert_equal assumes it will only ever be called with primitives.

So I put together a little bit of code to help out. The simplest solution I can think of uses json and diff, so I thought I'd call it assert_not_diff
require 'json'
require 'Tempfile'

def assert_not_diff(lhs,rhs)
  if lhs != rhs
    puts `diff -y #{file_for lhs} #{file_for rhs}`
  end
end

def file_for(obj)
  exp = Tempfile.new("bk", "/tmp").open
  exp.write(JSON.pretty_generate(obj))
  exp.close
  exp.path
end

expected = [1,99,2,3,{:a=>34,:b=>43}]
actual = [1,2,3,4,{:a=>324,:c=>555,:b=>43},5]
assert_not_diff expected, actual
This produces:
[                  [
  1,                 1,
  99,            <
  2,                 2,
  3,                 3,
                 >   4,
  {                  {
    "a": 34,     |     "a": 324,
                 >     "c": 555,
    "b": 43            "b": 43
  }              |   },
                 >   5
]                  ]
Which I think is a lot more useful.
Hope this proves useful to someone!

No comments:

Post a Comment