用于比较具有类似键的哈希的代码段

时间:2013-08-26 21:41:03

标签: ruby-on-rails ruby hash

我正在编写rails的集成测试,我想比较用发送的JSON对象创建的对象。返回的对象与发送的对象不完全相同,(即)它具有对象发送的密钥,因为我使用活动模型序列化器来提取返回对象中的关联。基本上,我只想比较两个对象之间的所有相同的键,看它是否相同。如果有一个干净,高效的代码片段可以帮我这么做!

3 个答案:

答案 0 :(得分:2)

TL; DR

“聪明”测试代码很少有用。每个测试应该尽可能简单,它应该测试某个对象的行为而不是它的组成。但总有办法聪明。

使用阵列交点

一种难以理解的聪明方法是使用Array#&来查找键的交集,然后查找值之间的相等性。这将在相对平坦的哈希上工作。例如:

hash1 = {:key1=>"value1", :key2=>"value2", :key3=>"value3", :key4=>"value4"}
hash2 = {:key1=>"value1", :key2=>"value2", :key5=>"value5"}
Array(hash1.keys & hash2.keys).map { |k| hash1[k] == hash2[k] }.uniq
#=> [true]

如果你正在使用RSpec进行测试,你可以这样说:

it 'has some matching key/value pairs' do
  # ... populate hash1
  # ... populate hash2
  Array(hash1.keys & hash2.keys).
    map { |k| hash1[k] == hash2[k] }.uniq.should == [true]
end

当然,如果期望是假的,那么你就不会真正知道原因,或者哪个键/值对错了。这只是您应该始终使用固定输入和输出进行测试的众多原因之一,而不是尝试进行动态比较。

答案 1 :(得分:0)

首先,找到两个哈希包含的键,然后比较这些键的值:

hash1 = {:key1 => "value1", :key2 => "value2", :key3 => "value3", :key4 => "value4"}
hash2 = {:key1 => "value1", :key2 => "value2", :key5 => "value5"}

hash1_keys = hash1.keys
hash2_keys = hash2.keys

comparable_keys = hash1_keys.select{|key| hash2_keys.include?(key)}

comparable_keys.each do |key|
  hash1[key].should == hash2[key]
end

答案 2 :(得分:0)

您可以使用Hash#slice,这是一个Active Support核心扩展程序。

例如,如果要检查的密钥为:a, :b, :c,但结果包含:a, :b, :c, :d,则slice会将结果缩小为仅包含您关注的密钥:

expected = { :a => 1, :b => 2, :c => 3 }
result   = { :a => 1, :b => 2, :c => 3, :d => 4 }

result.slice(:a, :b, :c) == expected
# => true

如果您收到NoMethodError: undefined method 'slice'例外,则需要active_support/core_ext/hash/slice

相关问题