Method to separate unit-test methods and data?


N

Nick Daly

Hi,

I was wondering if it's possible / if there are any simple methods
known of storing unit-test functions and their data in separate files?

Perhaps this is a strange request, but it does an excellent job of
modularizing code.  As far as revision control goes, it makes it
easier to discern between new or changed test cases, and changes in
the test data.

I've worked through this idea a bit and actually have a nearly working
model.  For example, when testing a class, I have a test module, which
contains a class for testing each method of the class.  This allows me
to generalize each method's parameters into each class, which can then
be overridden by the config file's data, something like as follows
(with a really arbitrary example, Python 2.5 code):


Demo code (midpoint.py):
=======================

class Midpoint(object):

   def __init__(self, a, b):
       self.a = a
       self.b = b

   def mid():
       return (self.a + self.b) / 2.0

   def sum()
       return (self.a + self.b)



Testing Code (test_Midpoint.py):
===============================

import unittest
import midpoint
import sys, ConfigParser as configparser


# set up the config file that overrides each class's data
config = configparser.SafeConfigParser()
config.read(sys.argv[0])


class test_Midpoint_mid(unittest.TestCase):
   def __init__(self):

       # default testing values
       self.none_values = ((None, 1),
                           (0, None))

       # override the default values with the config file values
       for key, value in config.items(self.__class__.__name__):
           if value:
               setattr(self, key, value)


   # a few tests of the method
   def test_rejectNone(self):
       for tests in self.none_values:
           self.assertRaises(TypeError,
               midpoint.Midpoint(tests[0], tests[1]).mid)

# and repeat the concept for class test_Midpoint_sum



Config Code (test_Midpoint.cfg):
==============================

# override the default values of the test class's members

[test_Midpoint_mid]
none_values = ((-1, None),
              (None, -12.8))



What I haven't yet figured out how to do though, is properly override
the default class member values with values from the config file.  The
config file's data is loaded as a string instead of as a list, as I'd
want.  This causes all the tests to fail, as while none_values needs
to be interpreted as a list, it is instead understood as:

" ((-1, None),\n               (None, -12.8))"

Does anyone have any solutions for these problems?  First, is there a
known and simple way to separate unit-test data and methods into
separate files?  Secondly, if not, is there a simple way to convert
strings into other base types, like lists, dictionaries, and so forth?
Or, am I going to have to write my own list-parsing methods?  Would
pickling help?  I haven't yet had a chance to look into if or how that
would work...  If there's anything else I can clarify about this
request, feel free to let me know.

Thanks for any help you can provide,
Nick
 
Ad

Advertisements

L

Lie Ryan

Nick said:
Hi,

I was wondering if it's possible / if there are any simple methods
known of storing unit-test functions and their data in separate files?

Perhaps this is a strange request, but it does an excellent job of
modularizing code. As far as revision control goes, it makes it
easier to discern between new or changed test cases, and changes in
the test data.
Does anyone have any solutions for these problems? First, is there a
known and simple way to separate unit-test data and methods into
separate files? Secondly, if not, is there a simple way to convert
strings into other base types, like lists, dictionaries, and so forth?
Or, am I going to have to write my own list-parsing methods? Would
pickling help? I haven't yet had a chance to look into if or how that
would work... If there's anything else I can clarify about this
request, feel free to let me know.

It is usually not a very good idea to complicate the testing framework
with configuration files (as then you will have two things to be
tested). Unless the testing data is very huge (so huge that it
interferes with reading and writing the testing code), and huge data is
necessary for the test, it is much simpler and better to just put the
data into the test code. In cases where you want to have fairly complex
object (list, etc) you can "import" the test data. Pickling is usually
unnecessary unless you want to store instance data (classes, etc).

-- code.py --
def add(a, b):
return a + b

-- test.py --
import unittest

# import the file we're testing
import code

# imports the data from separate file
from testdata import data

class AddCase(unittest.TestCase):
def test_add():
for case in data:
self.assertEqual(code.add(case[0], case[1]), case[2])

-- testdata.py --
data = [(0, 0, 0),
(1, 0, 1),
(0, 1, 1),
(1, -1, 0),
]
 

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

Top