Passing data to tests with test/unit

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.

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.

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.

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

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

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

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