Sharing objects between tests (revisited?)

I don’t know if I’ve asked this on this list before or only on irc (I
can’t find an earlier post on the subject, so I appologize if I’m asking
this a second time; I don’t remember the answer).

I have a number of tests that create some object. The tests are not
unit tests, but I am using a unit test framework (RUNIT or Test::Unit)
to write the tests. This object is expensive (time-wise) to create, and
I would like to share the object between my tests. If I write this:

class MyTest < Test::Unit::TestCase
def setup
@f = Foo.new
end

def test_1
end

def test_2
end

end

then @f gets constructed twice; once for each instance of MyTest.

I’m currently doing this instead:

$f = Foo.new

class MyTest < Test::Unit::TestCase
def setup
@f = $f
end

def test_1
end

def test_2
end

end

but surely there has to be a better way! What can I do?

Paul

I don’t know if I’ve asked this on this list before or only on irc (I
can’t find an earlier post on the subject, so I appologize if I’m asking
this a second time; I don’t remember the answer).

I have a number of tests that create some object. The tests are not
unit tests, but I am using a unit test framework (RUNIT or Test::Unit)
to write the tests. This object is expensive (time-wise) to create, and
I would like to share the object between my tests. If I write this:

class MyTest < Test::Unit::TestCase
def setup
@f = Foo.new

How about  
    @f ||= Foo.new
···

----- Original Message -----
From: “Paul Brannan” pbrannan@atdesk.com
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Tuesday, April 01, 2003 10:35 AM
Subject: sharing objects between tests (revisited?)

end

def test_1
end

def test_2
end

end


Gennady.

I don’t know if I’ve asked this on this list before or only on irc (I
can’t find an earlier post on the subject, so I appologize if I’m asking
this a second time; I don’t remember the answer).

I have a number of tests that create some object. The tests are not
unit tests, but I am using a unit test framework (RUNIT or Test::Unit)
to write the tests. This object is expensive (time-wise) to create, and
I would like to share the object between my tests. If I write this:

class MyTest < Test::Unit::TestCase
def setup
@f = Foo.new

How about  
    @f ||= Foo.new
···

----- Original Message -----
From: “Paul Brannan” pbrannan@atdesk.com
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Tuesday, April 01, 2003 10:35 AM
Subject: sharing objects between tests (revisited?)

end

def test_1
end

def test_2
end

end


Gennady.

I don’t know if I’ve asked this on this list before or only on irc (I
can’t find an earlier post on the subject, so I appologize if I’m asking
this a second time; I don’t remember the answer).

I have a number of tests that create some object. The tests are not
unit tests, but I am using a unit test framework (RUNIT or Test::Unit)
to write the tests. This object is expensive (time-wise) to create, and
I would like to share the object between my tests. If I write this:

class MyTest < Test::Unit::TestCase
def setup
@f = Foo.new

How about  
    @f ||= Foo.new
···

----- Original Message -----
From: “Paul Brannan” pbrannan@atdesk.com
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Tuesday, April 01, 2003 10:35 AM
Subject: sharing objects between tests (revisited?)

end

def test_1
end

def test_2
end

end


Gennady.

I don’t know if I’ve asked this on this list before or only on irc (I
can’t find an earlier post on the subject, so I appologize if I’m asking
this a second time; I don’t remember the answer).

I have a number of tests that create some object. The tests are not
unit tests, but I am using a unit test framework (RUNIT or Test::Unit)
to write the tests. This object is expensive (time-wise) to create, and
I would like to share the object between my tests. If I write this:

class MyTest < Test::Unit::TestCase
def setup
@f = Foo.new

How about  
    @f ||= Foo.new
···

----- Original Message -----
From: “Paul Brannan” pbrannan@atdesk.com
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Tuesday, April 01, 2003 10:35 AM
Subject: sharing objects between tests (revisited?)

end

def test_1
end

def test_2
end

end


Gennady.

In article 20030401183531.GK24880@atdesk.com,

I don’t know if I’ve asked this on this list before or only on irc (I
can’t find an earlier post on the subject, so I appologize if I’m asking
this a second time; I don’t remember the answer).

I have a number of tests that create some object. The tests are not
unit tests, but I am using a unit test framework (RUNIT or Test::Unit)
to write the tests. This object is expensive (time-wise) to create, and
I would like to share the object between my tests. If I write this:

class MyTest < Test::Unit::TestCase
def setup
@f = Foo.new
end

def test_1
end

def test_2
end
end

then @f gets constructed twice; once for each instance of MyTest.

I’m currently doing this instead:

$f = Foo.new

class MyTest < Test::Unit::TestCase
def setup
@f = $f
end

def test_1
end

def test_2
end
end

but surely there has to be a better way! What can I do?

What if you make it a class variable instead?
Something like:

class MyTest < Test::Unit::TestCase
@@f = Foo.new

def test1
… do stuff with @@f
end

def test2
… do stuff with @@f
end
end

Phil

···

Paul Brannan pbrannan@atdesk.com wrote:

Paul,

One thing to think about is why that object is expensive to create and
whether it can be done another way. I don’t know anything about the
object you want to test, but I find that if a test is expensive,
that’s because:

  1. The test relies on external resources – database, filesystem,
    network – and I might be better off writing a mock object to simulate
    those resources.
  2. The test relies on extremely complex setup, and I might be better
    off trying to break the object down into smaller parts so I can test
    its interactions in isolation.

I find that when testing gets hard, or slow, I do less of it, and then
inevitably I end up regretting that laziness later … So I try to do
the up-front work to make testing fast and easy, so I can always do
lots of it without feeling like I’m forcing myself.

Francis

Paul Brannan pbrannan@atdesk.com wrote in message news:20030401183531.GK24880@atdesk.com

···

I have a number of tests that create some object. The tests are not
unit tests, but I am using a unit test framework (RUNIT or Test::Unit)
to write the tests. This object is expensive (time-wise) to create, and
I would like to share the object between my tests.

Sorry for multiple posts, it is my company’s mail server fault :-(.
Switching to my personal mail account.
Gennady.

···

----- Original Message -----
From: “Gennady” gfb@tonesoft.com
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Tuesday, April 01, 2003 10:52 AM
Subject: Re: sharing objects between tests (revisited?)

----- Original Message -----
From: “Paul Brannan” pbrannan@atdesk.com
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Tuesday, April 01, 2003 10:35 AM
Subject: sharing objects between tests (revisited?)

I don’t know if I’ve asked this on this list before or only on irc (I
can’t find an earlier post on the subject, so I appologize if I’m asking
this a second time; I don’t remember the answer).

I have a number of tests that create some object. The tests are not
unit tests, but I am using a unit test framework (RUNIT or Test::Unit)
to write the tests. This object is expensive (time-wise) to create, and
I would like to share the object between my tests. If I write this:

class MyTest < Test::Unit::TestCase
def setup
@f = Foo.new

How about
    @f ||= Foo.new
end

def test_1
end

def test_2
end

end


Gennady.

This doesn’t work, since there is a different instance of MyTest for
each test_ method it has. You can verify this by printing id from
the setup() method.

Paul

···

On Wed, Apr 02, 2003 at 03:50:53AM +0900, Gennady wrote:

How about  
    @f ||= Foo.new

Your statements are correct for unit tests.

This test is intended to be an integration test for a system that is
distributed across a network. In order to completely test the system,
the test must make lots of network connections to each of the pieces of
the system, so it can validate that the pieces are correctly
communicating with each other.

I considered trying to test integration between only two pieces at any
given time, but implementing such a test would take a very long time,
since there is one piece of the system that talks to all the other
pieces of the system. Simulating those interactions is a lot of work,
since the communication is with CORBA, and Ruby does not speak CORBA
well.

Paul

···

On Wed, Apr 02, 2003 at 07:30:24PM +0900, Francis Hwang wrote:

Paul,

One thing to think about is why that object is expensive to create and
whether it can be done another way. I don’t know anything about the
object you want to test, but I find that if a test is expensive,
that’s because:

  1. The test relies on external resources – database, filesystem,
    network – and I might be better off writing a mock object to simulate
    those resources.
  2. The test relies on extremely complex setup, and I might be better
    off trying to break the object down into smaller parts so I can test
    its interactions in isolation.

Then if I require the file with MyTest but I never run MyTest, I still
create Foo. I instead do this:

class MyTest < Test::Unit::TestCase
@@setup_once = false

def setup
  if not @@setup_once then
    @@f = Foo.new
    @@setup_once = true
  end
end

def test1
end

def test2
end

end

Still, I can’t help but think there is a better way.

Paul

···

On Wed, Apr 02, 2003 at 04:27:46AM +0900, Phil Tomson wrote:

What if you make it a class variable instead?
Something like:

class MyTest < Test::Unit::TestCase
@@f = Foo.new

def test1
… do stuff with @@f
end

def test2
… do stuff with @@f
end
end

require ‘test/unit’

class Foo
  def initialize
    puts "In create."
  end
end

class MyTest < Test::Unit::TestCase
  def setup
    @@f = Foo.new unless 

self.class.class_variables.include?(“@@f”)
end

  def test1
  end

  def test2
  end
end

This is harder than it should be because @@f ||= Foo.new is not
legal in 1.6.8; perhaps it has been made legal in 1.8?

-austin
– Austin Ziegler, austin@halostatue.ca on 2003.04.02 at 10:59:58

···

On Thu, 3 Apr 2003 00:25:37 +0900, Paul Brannan wrote:

On Wed, Apr 02, 2003 at 04:27:46AM +0900, Phil Tomson wrote:
Then if I require the file with MyTest but I never run MyTest, I
still create Foo.

Or shorter: “unless defined? @@f

It’s a shame that you can’t do

@@f ||= Foo.new

as this generates a hard error (but I really must get round to installing a
1.8 preview so I can see if that’s changed)

Regards,

Brian.

···

On Thu, Apr 03, 2003 at 01:22:17AM +0900, Austin Ziegler wrote:

class MyTest < Test::Unit::TestCase
  def setup
    @@f = Foo.new unless

self.class.class_variables.include?(“@@f”)
end