module Minitest::Assertions

Constants

ELUCIDATABLE_CLASSES
METHOD_FOR_CLASS

Public Instance Methods

assert_equal(expected, actual, msg=nil) click to toggle source
# File lib/minitest_lucid.rb, line 11
def assert_equal(expected, actual, msg=nil)
  begin
    old_assert_equal(expected, actual, msg)
  rescue Minitest::Assertion => x
    elucidate(x, expected, actual, msg)
  end
end
Also aliased as: old_assert_equal
elucidate(exception, expected, actual, msg) click to toggle source
# File lib/minitest_lucid.rb, line 47
def elucidate(exception, expected, actual, msg)
  elucidation_method  =
      lookup(expected, actual) ||
      lookup(actual, expected) ||
      poll(expected, actual)
  if elucidation_method
    lines = ['']
    lines.push('{')
    lines.push("  :message => '#{msg}',") if msg
    send(elucidation_method, exception, expected, actual, lines)
    lines.push('}')
    lines.push('')
    message = lines.join("\n")
    new_exception = exception.exception(message)
    new_exception.set_backtrace(exception.backtrace)
    raise new_exception
  else
    raise
  end
end
elucidate_array(exception, expected, actual, lines) click to toggle source
# File lib/minitest_lucid.rb, line 68
def elucidate_array(exception, expected, actual, lines)
  sdiff = Diff::LCS.sdiff(expected, actual)
  changes = {}
  statuses = {
      '!' => 'changed',
      '+' => 'unexpected',
      '-' => 'missing',
      '=' => 'unchanged'
  }
  sdiff.each_with_index do |change, i|
    status = statuses.fetch(change.action)
    key = "change_#{i}"
    change_data = {
        :status => status,
        :"old_index_#{change.old_position}" => change.old_element.inspect,
        :"new_index_#{change.new_position}" => change.new_element.inspect,
    }
    changes.store(key, change_data)
  end
  lines.push('elucidation = [')
  changes.each_pair do |category, change_data|
    status = change_data.delete(:status)
    if status == 'unexpected'
      change_data.delete_if {|key, value| key.match(/old/) }
    end
    if status == 'missing'
      change_data.delete_if {|key, value| key.match(/new/) }
    end
    lines.push('  {')
    lines.push("  :status => :#{status},")
    change_data.each_pair do |k, v|
      lines.push("  :#{k} => #{v},")
    end
    lines.push('  },')
  end
  lines.push(']')
end
elucidate_hash(exception, expected, actual, lines) click to toggle source
# File lib/minitest_lucid.rb, line 106
def elucidate_hash(exception, expected, actual, lines)
  expected_keys = expected.keys
  actual_keys = actual.keys
  keys = Set.new(expected_keys + actual_keys)
  h = {
      :missing_pairs => {},
      :unexpected_pairs => {},
      :changed_values => {},
      :ok_pairs => {},
  }
  keys.each do |key|
    expected_value = expected[key]
    actual_value = actual[key]
    case
      when expected_value && actual_value
        if expected_value == actual_value
          h[:ok_pairs].store(key, expected_value)
        else
          h[:changed_values].store(key, [expected_value, actual_value])
        end
      when expected_value
        h[:missing_pairs].store(key, expected_value)
      when actual_value
        h[:unexpected_pairs].store(key, actual_value)
      else
        fail [expected_value, actual_value].inspect
    end
  end
  lines.push('  :expected => {')
  lines.push("    :class => #{expected.class},")
  lines.push("    :size => #{expected.size},")
  lines.push('  },')
  lines.push('  :actual => {')
  lines.push("    :class => #{actual.class},")
  lines.push("    :size => #{actual.size},")
  lines.push('  },')
  lines.push('  :elucidation => {')
  h.each_pair do |category, items|
    lines.push("    #{pretty(category)} => {")
    items.each_pair do |key, value|
      if value.instance_of?(Array)
        expected, actual = *value
        lines.push("      #{pretty(key)} => {")
        lines.push("        :expected => #{pretty(expected)},")
        lines.push("        :got      => #{pretty(actual)},")
        lines.push('      },')
      else
        lines.push("      #{pretty(key)} => #{pretty(value)},")
      end
    end
    lines.push('    },')
  end
  lines.push('  }')
end
elucidate_set(exception, expected, actual, lines) click to toggle source
# File lib/minitest_lucid.rb, line 161
def elucidate_set(exception, expected, actual, lines)
  result = {
      :missing => expected.difference(actual),
      :unexpected => actual.difference(expected),
      :ok => expected.intersection(actual),
  }
  lines.push('  :expected => {')
  lines.push("    :class => #{expected.class},")
  lines.push("    :size => #{expected.size},")
  lines.push('  },')
  lines.push('  :actual => {')
  lines.push("    :class => #{actual.class},")
  lines.push("    :size => #{actual.size},")
  lines.push('  },')
  lines.push('  :elucidation => {')
  result.each_pair do |category, items|
    lines.push("    #{pretty(category)} => {")
    items.each do |member|
      lines.push("      #{pretty(member)},")
    end
    lines.push('    },')
  end
  lines.push('  }')
end
elucidate_struct(exception, expected, actual, lines) click to toggle source
# File lib/minitest_lucid.rb, line 186
def elucidate_struct(exception, expected, actual, lines)
  expected_members = expected.members
  actual_members = actual.members
  members = Set.new(expected_members + actual_members)
  h = {
      :changed_values => {},
      :ok_values => {},
  }
  members.each do |member|
    expected_value = expected[member]
    actual_value = actual[member]
    if expected_value == actual_value
      h[:ok_values].store(member, expected_value)
    else
      h[:changed_values].store(member, [expected_value, actual_value])
    end
  end
  lines.push('  :expected => {')
  lines.push("    :class => #{expected.class},")
  lines.push("    :size => #{expected.size},")
  lines.push('  },')
  lines.push('  :actual => {')
  lines.push("    :class => #{actual.class},")
  lines.push("    :size => #{actual.size},")
  lines.push('  },')
  lines.push('  :elucidation => {')
  h.each_pair do |category, items|
    lines.push("    #{pretty(category)} => {")
    items.each_pair do |member, value|
      if value.instance_of?(Array)
        expected, actual = *value
        lines.push("      #{pretty(member)} => {")
        lines.push("        :expected => #{pretty(expected)},")
        lines.push("        :got      => #{pretty(actual)},")
        lines.push('      },')
      else
        lines.push("      #{pretty(member)} => #{pretty(value)},")
      end
    end
    lines.push('    },')
  end
  lines.push('  }')
end
lookup(one_object, other_object) click to toggle source

Lookup objects in hash.

# File lib/minitest_lucid.rb, line 28
def lookup(one_object, other_object)
  if ELUCIDATABLE_CLASSES.include?(one_object.class)
    if other_object.kind_of?(one_object.class)
      return METHOD_FOR_CLASS.fetch(one_object.class)
    end
  end
  nil
end
old_assert_equal(expected, actual, msg=nil)
Alias for: assert_equal
poll(expected, actual) click to toggle source

Poll with kind_of?.

# File lib/minitest_lucid.rb, line 38
def poll(expected, actual)
  METHOD_FOR_CLASS.each_pair do |klass, method|
    next unless expected.kind_of?(klass)
    next unless actual.kind_of?(klass)
    return method
  end
  nil
end
pretty(arg) click to toggle source
# File lib/minitest_lucid.rb, line 230
def pretty(arg)
  case
    when arg.kind_of?(Symbol)
      ":#{arg}"
    when arg.kind_of?(String)
      "'#{arg}'"
    when arg.kind_of?(Numeric)
      arg
    else
      arg.inspect
  end
end