0

I have a test in Ruby as follows

def testSomeObjectsAreEqual
  assert_equal( object1, object2 )
end

When this test fails I get an error message which states that the two objects are not equal and gives the following style of message for the expected and actual values:

<#<Java:com.mynamespace.MyClass:0x1232b3e12>> expected but was
<#<Java:com.mynamespace.MyClass:0x489654ebd>>.

As you can see I am using JRuby to instantiate a Java class and that is the object being compared. I've trying printing object.to_s in Ruby and that prints a sensible looking message, it seems to map directly to the Java declared toString() method for MyClass, however to_s does not seem to be used for the failure message of the assertion. Is there anyway I can get Ruby test/unit to use the to_s value of the objects as this would make the failure messages much more useful for me?

J.Churchill
  • 430
  • 3
  • 12

4 Answers4

1

Test::Unit (I presume that is what you are using) uses #pretty_inspect to convert objects into printable form. You can override/monkeypatch this for your class; you only need to do so in the test script.

Michael Slade
  • 13,802
  • 2
  • 39
  • 44
  • Well that's what I hoped would happen but as I mentioned in my question, to_s is implemented in my class, and even when I explicitly extend the class in Ruby to specify to_s so it calls the Java classes toString() method it still prints the object address, rather than the object content (as would be given by to_s)... – J.Churchill May 05 '12 at 11:02
  • I monkeypatched my class with #inspect so that it calls the Java toString() and that does the trick! I guess for Java classes in JRuby the default inspect implementation cannot access the private members, hence all I get is a reference to the. This question is similar to what I was asking but not precisely the same [http://stackoverflow.com/questions/2625667/why-do-this-ruby-object-have-two-to-s-and-inspect-methods-that-do-the-same-thing]. Accepting your answer, thanks. – J.Churchill May 05 '12 at 19:34
1

Уou can add some annotation to the failure message:

assert_equal( object1, object2, "my message: #{object1.to_s},  #{object2.to_s}" )
NickRndl
  • 11
  • 1
  • Thanks for your answer, I had considered this but was rather hoping the framework would give me a pretty failure message already. Makes me wonder if I'm doing something else wrong... – J.Churchill May 05 '12 at 16:28
0

I am not sure if I got this properly. But, you can make a method in your class which accepts the argument as the object(of it's own class). If the comparison fails, you can raise the exception(say) and then correspondingly assert it by:

assert_raises(TypeError){object1.compare(object2)}

May be wrong, please to correct me here.

kiddorails
  • 12,961
  • 2
  • 32
  • 41
  • I see what you mean but the class already has it's equals() method, which I presume is being used for comparison. What I'm really after is automatic conversion of the objects to strings in the failure message. For example JUnit for Java will do this is you have implemented toString() for your class. – J.Churchill May 05 '12 at 11:00
0

I'd recommend that rather than comparing the objets directly in the unit test, you test that different attributes are the same -- this will give you more information when a portion of the test fails. There are subtleties of direct object comparison that you could run into that may add no value to your overall test.

So, if the object had attributes that included first_name, last_name and status, I'd recommend rewriting the test this way:

def testSomeObjectsAreEqual
  assert_equal( object1.first_name, object2.first_name )
  assert_equal( object1.last_name, object2.last_name )
  assert_equal( object1.status, object2.status )
  ... etc ...
end
Kevin Bedell
  • 13,254
  • 10
  • 78
  • 114