# Passing data to tests with test/unit

**URL:** <https://www.ruby-forum.com/t/passing-data-to-tests-with-test-unit/90456>\
**Category:** Ruby\
**Created:** [March 28, 2007, 11:23pm UTC](https://www.ruby-forum.com/t/passing-data-to-tests-with-test-unit/90456 "2007-03-28T23:23:12Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![burrowsm](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/d78d45/32.png) [@burrowsm](https://www.ruby-forum.com/u/burrowsm)\
**Post date:** [March 28, 2007, 11:23pm UTC](https://www.ruby-forum.com/t/passing-data-to-tests-with-test-unit/90456/1 "2007-03-28T23:23:12Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![burrowsm](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/d78d45/32.png) [@burrowsm](https://www.ruby-forum.com/u/burrowsm)\
**Post date:** [March 29, 2007, 7:13am UTC](https://www.ruby-forum.com/t/passing-data-to-tests-with-test-unit/90456/2 "2007-03-29T07:13:18Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![burrowsm](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/d78d45/32.png) [@burrowsm](https://www.ruby-forum.com/u/burrowsm)\
**Post date:** [March 29, 2007, 5:41pm UTC](https://www.ruby-forum.com/t/passing-data-to-tests-with-test-unit/90456/3 "2007-03-29T17:41:51Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![burrowsm](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/d78d45/32.png) [@burrowsm](https://www.ruby-forum.com/u/burrowsm)\
**Post date:** [March 29, 2007, 6:52pm UTC](https://www.ruby-forum.com/t/passing-data-to-tests-with-test-unit/90456/4 "2007-03-29T18:52:38Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![burrowsm](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/d78d45/32.png) [@burrowsm](https://www.ruby-forum.com/u/burrowsm)\
**Post date:** [March 29, 2007, 9:10pm UTC](https://www.ruby-forum.com/t/passing-data-to-tests-with-test-unit/90456/5 "2007-03-29T21:10:32Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![burrowsm](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/d78d45/32.png) [@burrowsm](https://www.ruby-forum.com/u/burrowsm)\
**Post date:** [March 29, 2007, 9:31pm UTC](https://www.ruby-forum.com/t/passing-data-to-tests-with-test-unit/90456/6 "2007-03-29T21:31:36Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![burrowsm](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/d78d45/32.png) [@burrowsm](https://www.ruby-forum.com/u/burrowsm)\
**Post date:** [March 30, 2007, 5:43pm UTC](https://www.ruby-forum.com/t/passing-data-to-tests-with-test-unit/90456/7 "2007-03-30T17:43:55Z")

</div>

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
