Test::Unit - same test, different "args"

L

Luke St.Clair

I need to run the same unit test case more than 10 times (around 150
tests in the test case), with 2-3 parameters changed each time.

For instance, if I had unit tests to examine a "Person", with a
required parameter "name" - let's say I want to run the same
Test::Unit::TestCase on 10 different people, with different names but
everything else the same. All test cases run the same code, just with
the one (or two) parameters tweaked.

Let's say I have 150 tests for a Person - I'd rather not end up with
1500 tests, each of the 150 tests exactly duplicated for a different
"name".

I'll have a hierarchy of tests cases, in suites, which may help

Is there some way to:
1) set a global variable in the "parent" test suite that the children
see? Seems like the answer to this is no
2) Pass an arg to the test case as a whole? Don't see anyway to do
this in the docs
3) Do something else that will keep this test code compliant with DRY?

What's the right approach here?
 
M

Michael Malone

om>
X-Received-From: This message has been automatically forwarded from the ruby-talk mailing list by a gateway at comp.lang.ruby. If it is SPAM, it did not originate at comp.lang.ruby. Please report the original sender, and not us. Thanks! For more details about this gateway, please visit: http://blog.grayproductions.net/categories/the_gateway
X-Mail-Count: 331902
X-Ml-Name: ruby-talk
X-Rubymirror: Yes
X-Ruby-Talk: <[email protected]>
Bytes: 3945
X-Original-Bytes: 3810
Xref: number1.nntp.dca.giganews.com comp.lang.ruby:326205
I need to run the same unit test case more than 10 times (around 150
tests in the test case), with 2-3 parameters changed each time.

For instance, if I had unit tests to examine a "Person", with a
required parameter "name" - let's say I want to run the same
Test::Unit::TestCase on 10 different people, with different names but
everything else the same. All test cases run the same code, just with
the one (or two) parameters tweaked.

Let's say I have 150 tests for a Person - I'd rather not end up with
1500 tests, each of the 150 tests exactly duplicated for a different
"name".

I'll have a hierarchy of tests cases, in suites, which may help

Is there some way to:
1) set a global variable in the "parent" test suite that the children
see? Seems like the answer to this is no
2) Pass an arg to the test case as a whole? Don't see anyway to do
this in the docs
3) Do something else that will keep this test code compliant with DRY?

What's the right approach here?
my first thought is to have your test_something methods call protected
methods of the class (that you create). Just because it's a unit test
doesn't mean it's not also a perfectly normal object - I often forget
that one. Using this in conjunction with a setup method and you should
be able to get things going as you want. IMHO hardwiring test data into
your test classes isn't a Bad Thing. It helps you keep your data/data
structures smart and your code dumb, so you can simply have an array or
something similar of the parameters you want, and then cycle through
those.

HTH,
Michael

=======================================================================
This email, including any attachments, is only for the intended
addressee. It is subject to copyright, is confidential and may be
the subject of legal or other privilege, none of which is waived or
lost by reason of this transmission.
If the receiver is not the intended addressee, please accept our
apologies, notify us by return, delete all copies and perform no
other act on the email.
Unfortunately, we cannot warrant that the email has not been
altered or corrupted during transmission.
=======================================================================
 
B

Brian Candler

Luke said:
Is there some way to:
1) set a global variable in the "parent" test suite that the children
see? Seems like the answer to this is no

Shoulda sits on top of Test::Unit and may be helpful. Something like
this:

class MyTest < Test::Unit::TestCase
context "top level" do
setup do
@stuff = ...
end

should "test something at top level" do
assert_equal 123, @stuff.size
end

context "inner level" do
setup do
@more_stuff = ...
end

should "test more" do
assert_equal @stuff.size, @more_stuff.size
end
end
end
end

See:
http://www.thoughtbot.com/projects/shoulda
http://mtnwestrubyconf2008.confreaks.com/12saleh.html
http://tammersaleh.com/system/assets/bdd_with_shoulda.pdf
 
L

Luke St.Clair

Put all the test_ methods into a module, and include it into 10 differentsuites:

class ATest < Test::Unit::TestCase; include Suite; setup; @me = 'a'; end; end
class BTest < Test::Unit::TestCase; include Suite; setup; @me = 'b'; end; end
class CTest < Test::Unit::TestCase; include Suite; setup; @me = 'c'; end; end
class DTest < Test::Unit::TestCase; include Suite; setup; @me = 'd'; end; end

there might be a less effusive way, but the Abstract Test Pattern is very
important to learn, so this is a good start...


Abstract Test is best to match an important class hierarchy in your code.
Otherwise, the question arises are you missing an abstraction? Could you
simplify something else, and test fewer permutations?

I think this is what I'm going to go with - I'll have a test case for
each possible param value (there are about 10), and each one will set
a few additional global variables. Then, each test case will include
the same module, which will call functions with params set by the
global variables.

Seems to be very DRY, as long as the set of param values is small (it
is in this case, and should stay small in the future).

Thanks -
 
L

Luke St.Clair

Shoulda sits on top of Test::Unit and may be helpful. Something like
this:

class MyTest < Test::Unit::TestCase
  context "top level" do
    setup do
      @stuff = ...
    end

    should "test something at top level" do
      assert_equal 123, @stuff.size
    end

    context "inner level" do
      setup do
        @more_stuff = ...
      end

      should "test more" do
        assert_equal @stuff.size, @more_stuff.size
      end
    end
  end
end


This seems incredibly useful - unfortunately, I can't use shoulda.
 
L

Luke St.Clair

I think this is what I'm going to go with - I'll have a test case for
each possible param value (there are about 10), and each one will set
a few additional global variables.  Then, each test case will include
the same module, which will call functions with params set by the
global variables.

The biggest issue I'm running into right now is not having startup(),
or code that runs once per test suite, not once per test case.

Is this in test::unit yet?
 
L

Luke St.Clair

The biggest issue I'm running into right now is not having startup(),
or code that runs once per test suite, not once per test case.

Is this in test::unit yet?

Better yet, is there some way to get around this?

Right now, I have like 8 test suite files, which do something like:

initialize_things(foo)

class MyTester < Test::Unit::TestCase
include cases1
include cases2
end

This works fine if I run the file directly, but I want a "master" test
runner that would require MyTester, MyOtherTester, MyFinalTester,
etc. In this case, initialize_things doesn't get called.

How can I replicate this startup() functionality that I need? I do
NOT want to use setup(), as it slows things down considerably.
 
L

Luke St.Clair

There are code samples and I think plugins which add that.

How about in the base module...

   def setup
     @@done ||= suite_setup()
   end

Then put what you want in the suite_setup ?

Yes, that's clearly the best way for me to do this outside of startup
() - don't know what I was thinking there.
 
P

Phlip

Luke said:
Yes, that's clearly the best way for me to do this outside of startup
() - don't know what I was thinking there.

I was thinking I don't know if that runs once per suite or once per test run...
 
K

Kouhei Sutou

Hi,

In <[email protected]>
"Re: Test::Unit - same test, different "args"" on Thu, 26 Mar 2009 08=
:26:47 +0900,
Luke St.Clair said:
=

The biggest issue I'm running into right now is not having startup(),=
or code that runs once per test suite, not once per test case.
=
Is this in test::unit yet?

Type 'sudo gem install test-unit'. Test::Unit 2.x supports
it:
http://test-unit.rubyforge.org/test-unit/classes/Test/Unit/TestCase.h=
tml

Thanks,
 
K

Kouhei Sutou

Hi,

In <[email protected]>
"Re: Test::Unit - same test, different "args"" on Wed, 25 Mar 2009 04=
:51:52 +0900,
Luke St.Clair said:
This seems incredibly useful - unfortunately, I can't use shoulda.

Test::Unit 2.x also supports that usage with natural Ruby
syntax:

# From http://test-unit.rubyforge.org/svn/trunk/sample/test_user.rb

class UserTest < Test::Unit::TestCase
def setup
@user =3D "me"
end

def test_full_name
assert_equal("me", @user)
end

class ProfileTest < UserTest
setup
def setup_profile
@user +=3D ": profile"
end

def test_has_profile
assert_match(/: profile/, @user)
end
end
end


Thanks,
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,234
Latest member
SkyeWeems

Latest Threads

Top