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.
Matt B. (Guest)
on 2007-03-29 01: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.
Brian C. (Guest)
on 2007-03-29 09:13
(Received via mailing list)
On Thu, Mar 29, 2007 at 06:23:14AM +0900, Matt B. 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.
Matt B. (Guest)
on 2007-03-29 19: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 C. wrote:
> On Thu, Mar 29, 2007 at 06:23:14AM +0900, Matt B. 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.
unknown (Guest)
on 2007-03-29 20:52
(Received via mailing list)
On Fri, 30 Mar 2007, Matt B. 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
Brian C. (Guest)
on 2007-03-29 23:10
(Received via mailing list)
On Fri, Mar 30, 2007 at 12:41:54AM +0900, Matt B. 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
Nasir K. (Guest)
on 2007-03-29 23: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
Matt B. (Guest)
on 2007-03-30 19: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 K. 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.