我试图在Ruby中单元测试一个类的两个实例的相同性:
def test_example
a = Object.new
b = Object.new
assert_equal a, b
end
我理解这是失败的,因为实例是不同的变量,每个变量都有自己的内存指针。我所追求的是如果实例在所有方面都相同但是它们的参考指针都要通过这个测试。
这是一个更具参与性(如果做作)的例子:
# Let's stir up something...
class FooBar
attr_accessor :seed, :foo, :bar
def foo_the_bar()
@bar = @seed + @foo * 3
end
end
f = FooBar.new
f.seed = "Mountains "
f.foo = "are just mountains "
f.bar = "obliterate me!"
f.foo_the_bar
p f.bar # "Mountains are just mountains are just mountains are just mountains "
# So far so good, now let's test if one FooBar is same as another...
require 'test/unit'
class FooBarTest < Test::Unit::TestCase
# Test fails: <#<FooBar:0x9a40d18>> expected but was <#<FooBar:0x9a40d04>>.
# But what we really want is a way to make this pass
# since the objects are exactly the same in every respect,
# besides their pointers.
def test_foobar_1_init
f1 = FooBar.new
f2 = FooBar.new
assert_equal f1, f2
end
# Again, test fails, but we want it to pass,
# since the instance variables are the same.
def test_foobar_2_instance_var
f1 = FooBar.new
f2 = FooBar.new
f1.seed = "Santa says "
f1.foo = "ho "
f1.bar = "something"
f1.foo_the_bar
f2.seed = f1.seed
f2.foo = f1.foo
f2.foo_the_bar
assert_equal f1, f2
end
# This test fails for the wrong reason.
# We want this to fail because the instance variables are different.
# This test should also fail if we add a method to one of the instances,
# or make the instances differ from each some other way.
def test_foobar_3_diff
f1 = FooBar.new
f2 = FooBar.new
f1.seed = "Kitty goes "
f1.foo = "meow "
f1.foo_the_bar
f2.seed = "Doggies goes "
f2.foo = "woof "
f2.foo_the_bar
assert_equal f1, f2
end
end
答案 0 :(得分:1)
f1.attributes.keys.collect(&:to_sym).each do |field|
assert_equal f1.send(field), f2.send(field)
end
这将断言所有字段的相等性。但缺点是断言的数量。如果您不希望这种情况发生,请将id分配给像这样的对象
f1.id = 1
f2.id = 1
assert_equal f1, f2
但请务必不要保存可能导致不一致的对象。
答案 1 :(得分:1)
只需定义FooBar#==
方法:
class FooBar
def ==(other)
[bar, seed, foo] == [other.bar, other.seed, other.foo]
end
end
现在test_foobar_1_init
和test_foobar_2_instance_var
通过,test_foobar_3_diff
因正当理由而失败。
缺点是当您更改对象结构时,需要相应地修改==
方法。
答案 2 :(得分:-1)
根据apidock的源代码,assert_equals首先使用inspect
方法将对象转换为字符串。您应该为class FooBar
class FooBar
def inspect
# create a unique string of attributes here, maybe a json string.
end
end