Forum: Ruby passing data to tests with test/unit

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Da8facad4df4ab8fac7004e3b1394979?d=identicon&s=25 Matt Berney (mberney)
on 2007-03-28 23:23
I have a test case, based on the Test::Unit::TestCase. How does one pass
data to the test in such a way that the test can be run multiple times
with different input.

For example:

class TC_CreateOrder < Test::Unit::TestCase
  def test_NewOrder
    assert "order successful"
  end
end

Now, I want to be able to generate a new order for various order types,
(TYPE1, TYPE2, TYPE3, etc.)

class TS_OrderTests
  def self.suite
    suite = Test::Unit::TestSuite.new
    suite << TC_CreateOrder.suite # TYPE1 goes here
    suite << TC_CreateOrder.suite # TYPE2 goes here
    suite << TC_CreateOrder.suite # TYPE3 goes here
    return suite
  end
end

Test::Unit::UI::Console::TestRunner.run(TS_OrderTests)

Thanks in advance.
753dcb78b3a3651127665da4bed3c782?d=identicon&s=25 Brian Candler (Guest)
on 2007-03-29 07:13
(Received via mailing list)
On Thu, Mar 29, 2007 at 06:23:14AM +0900, Matt Berney wrote:
> end
>     return suite
>   end
> end
>
> Test::Unit::UI::Console::TestRunner.run(TS_OrderTests)

If it's only one test method, you can factor it out in the class:

class TC_CreateOrder < Test::Unit::TestCase
  def do_test(t)
    .. process t
  end

  def test_type1
    do_test(TYPE1)
  end

  def test_type2
    do_test(TYPE2)
  end

  def test_type3
    do_test(TYPE3)
  end
end

Otherwise, how about:

class TC_CreateOrder1 < TC_CreateOrder
  FIXTURE = TYPE1
end

class TC_CreateOrder2 < TC_CreateOrder
  FIXTURE = TYPE2
end

class TC_CreateOrder3 < TC_CreateOrder
  FIXTURE = TYPE3
end

(I'm not sure how you'd prevent the base test TC_CreateOrder being run)

Regards,

Brian.
Da8facad4df4ab8fac7004e3b1394979?d=identicon&s=25 Matt Berney (mberney)
on 2007-03-29 17:41
Thanks Brian,

This would work ok if there was only one test method and only 3 types.
Now let's say that I want to use this test technique multiple times,
with multiple test methods.  And, the data input is over 100 items.
Duplicating this structure 100 times doesn't seem tenable.

What I am really looking for is a data-driven test method, such that I
can use the same test case and pass it different data.  However, for
test execution and measurement purposes, it is preferable to record
these as separate tests.


Brian Candler wrote:
> On Thu, Mar 29, 2007 at 06:23:14AM +0900, Matt Berney wrote:
>> end
>>     return suite
>>   end
>> end
>>
>> Test::Unit::UI::Console::TestRunner.run(TS_OrderTests)
>
> If it's only one test method, you can factor it out in the class:
>
> class TC_CreateOrder < Test::Unit::TestCase
>   def do_test(t)
>     .. process t
>   end
>
>   def test_type1
>     do_test(TYPE1)
>   end
>
>   def test_type2
>     do_test(TYPE2)
>   end
>
>   def test_type3
>     do_test(TYPE3)
>   end
> end
>
> Otherwise, how about:
>
> class TC_CreateOrder1 < TC_CreateOrder
>   FIXTURE = TYPE1
> end
>
> class TC_CreateOrder2 < TC_CreateOrder
>   FIXTURE = TYPE2
> end
>
> class TC_CreateOrder3 < TC_CreateOrder
>   FIXTURE = TYPE3
> end
>
> (I'm not sure how you'd prevent the base test TC_CreateOrder being run)
>
> Regards,
>
> Brian.
Cb48ca5059faf7409a5ab3745a964696?d=identicon&s=25 unknown (Guest)
on 2007-03-29 18:52
(Received via mailing list)
On Fri, 30 Mar 2007, Matt Berney wrote:

> these as separate tests.
>


def setup
   TEST_DATA = YAML.load(IO.read(ENV['TEST_DATA']))  # TEST_DATA is a
filename for
                                                     # yaml data
end

TEST_DATA=a.yml ruby test/a.rb

-a
753dcb78b3a3651127665da4bed3c782?d=identicon&s=25 Brian Candler (Guest)
on 2007-03-29 21:10
(Received via mailing list)
On Fri, Mar 30, 2007 at 12:41:54AM +0900, Matt Berney wrote:
> This would work ok if there was only one test method and only 3 types.
> Now let's say that I want to use this test technique multiple times,
> with multiple test methods.  And, the data input is over 100 items.
> Duplicating this structure 100 times doesn't seem tenable.
...
> > end
But this was just an example; if this works then you can do it
dynamically.

How about something like:

$test_classes = []

fixtures = [TYPE1, TYPE2, TYPE3]
fixtures.each do |f|
  klass = Class.new(TC_CreateOrder)
  klass.const_set(:FIXTURE, f)
  $test_classes << klass  # to prevent garbage collection
end
9aafe2636a115bbdc137c93445054f22?d=identicon&s=25 Nasir Khan (Guest)
on 2007-03-29 21:31
(Received via mailing list)
You could write a private method in your test class which is called from
a
public test method which in turn gets the data from a YAML file or some
other data source.

e.g

------------------------------------------------------
require 'test/unit'

class MyTest < Test::Unit::TestCase

  def test_public
    3.times { |i| _test_private(i) }  # get your input data here before
calling private method
  end

  def _test_private(arg)
    puts  "Now testing with #{arg}"
    assert(true)
  end

private :_test_private
end

-------------------------------
Loaded suite test
Started
Now testing with 0
Now testing with 1
Now testing with 2

- nasir
Da8facad4df4ab8fac7004e3b1394979?d=identicon&s=25 Matt Berney (mberney)
on 2007-03-30 17:43
Thanks to everyone who posted responses.  Through a combination of your
feedback and experimentation, here is the solution I came up with:

class TC_CreateOrder < Test::Unit::TestCase
  def test_NewOrder
    orderTypeList = File.open('orders.yaml') { |yf| YAML::load(yf) }
    orderTypeList.each { |type|
      # perform the test
      assert "order successful"
      @_result.add_run
  end
end


The trick was the last line "@_result.add_run".  By adding this line,
each time through the loop increments the test count such that each
order is a separate test case.


Nasir Khan wrote:
> You could write a private method in your test class which is called from
> a
> public test method which in turn gets the data from a YAML file or some
> other data source.
>
> e.g
>
> ------------------------------------------------------
> require 'test/unit'
>
> class MyTest < Test::Unit::TestCase
>
>   def test_public
>     3.times { |i| _test_private(i) }  # get your input data here before
> calling private method
>   end
>
>   def _test_private(arg)
>     puts  "Now testing with #{arg}"
>     assert(true)
>   end
>
> private :_test_private
> end
>
> -------------------------------
> Loaded suite test
> Started
> Now testing with 0
> Now testing with 1
> Now testing with 2
>
> - nasir
This topic is locked and can not be replied to.