From: Eric Hodel Date: 2006-05-04T03:54:11+09:00 Subject: Re: Unit test setup On May 3, 2006, at 10:45 AM, Eust�quio Rangel wrote: > Hi. You're mixing up responses among different people here, and that is very poor mailing list etiquette. >> You don't need it and you don't want it. > > You can't be so sure about that all over the time. ;-) I'm 100% certain of that. If you think you need it your code isn't easily testable. You should refactor instead. >> Ruby doesn't have deconstructors at all. > > Yes, I know, I was trying to figure out some global method like the > "destroy" method on the unit testing class. I mean, a global "destroy" > like the global "setup". Not really C++ destroy stuff. > >> The easiest way to achieve a "global" test setup is by invoking >> explicitly the test runner: > > That worked, thanks! Btw, it was the only way I thought to test the > socket operations. Even if most tests are not on the correct > sequence (I > just need step 2 below are the first one - ok, it's requirement), I > can > make things like: > > 1 - Connect on the socket (the "global" setup). You should be using a stub instead. Here's what I've got for MogileFS: class FakeSocket def initialize @closed = false end def closed? @closed end def close @closed = true return nil end end That's all I need, so add methods to the stub as appropriate. > 2 - Send a hello and get an id. > 3 - List all the other users there. > 4 - Send a ping to make sure we're still there. > 5 - Send a quit, goodbye. > 6 - Close the socket. > > All the operations from 3 and below needs the id from 2, where the > server authorize the client with a password and return its id. You shouldn't be connecting to anything during a unit test. If you are it isn't really a test of a unit. > So if I open/close the socket on every test I lost the > authorization and the id. I use the asserts to test if the > authentication worked and returned a > valid id, if returns the user list, and so on. You shouldn't have to do all the setup for every test, just the setup for the test. You should be able to test sending a ping without fetching an id. You should be able to test sending a ping without an id. You may need to refactor your code. To help you on your way I've got another trick for you. I wrote a flickr library using open-uri. open-uri overrides Kernel#open, but I don't really want to connect to flickr to run my tests. Instead I just insert an open into my flickr class while testing that pretends to be flickr. You can do the same with a socket stub, just have the socket pretend it is already initialized and have it return the proper responses. class Flickr attr_accessor :responses, :uris def open(uri) @uris << uri yield StringIO.new(@responses.shift) end end class FlickrTest < Test::Unit::TestCase def setup @flickr = Flickr.new 'API_KEY' @flickr.responses = [] @flickr.uris = [] end def test_search_multipage @flickr.responses << <<-EOF [...] EOF @flickr.responses << <<-EOF [...] EOF photos = @flickr.search :user_id => '50178138@N00', :min_taken_date => Time.parse ('2005-10-21'), :per_page => 2 assert_equal 2, @flickr.uris.length assert_equal 'http://flickr.com/services/rest/...', @flickr.uris.first assert_equal 'http://flickr.com/services/rest/...', @flickr.uris.last assert_equal 3, photos.length assert_equal [59864477, 55457289, 55457233], photos.map { |p| p.photo_id } end end -- Eric Hodel - drbrain@segment7.net - http://blog.segment7.net This implementation is HODEL-HASH-9600 compliant http://trackmap.robotcoop.com