Unit testing "templates"?

Francis Avila francisgavila at yahoo.com
Sat Apr 12 02:28:09 EDT 2003


I have a class that is similar to the xdrlib.Unpacker class: you initialize
the class with some binary data, which is stuffed into an internal buffer
(with a pointer), and you then call various methods of the instance to
return chunks of interpreted data (via the struct module) until the buffer
is exhausted.

I'm now writing tests for these methods which instantiate the class with
known data and then call a method of that instance to get a known result.
But it's getting repetitive, and I'm wondering if there is a better way.

Here's a representative sample:

import unittest
import xdmcplib   #the module we're testing

class DatatypeUnpack(unittest.TestCase):
    """Verify xdmcplib.Unpacker conversions."""
    def testUnpackCard32(self):
        """unpack_card32() should return known result from known valid
input"""
        for value, data in ( (0,'\x00\x00\x00\x00'), (1,'\x00\x00\x00\x01'),
                             (2,'\x00\x00\x00\x02'),
(65535,'\x00\x00\xff\xff'),
                             (4294967295L,'\xff\xff\xff\xff') ):
            result = xdmcplib.Unpacker(data).unpack_card32()
            self.assertEqual(value, result)

    def testUnpackArray8(self):
        """unpack_array8() should return known result from known valid
input"""
        for value, data in ( ('','\x00\x00'), ('Test','\x00\x04Test') ):
            result = xdmcplib.Unpacker(data).unpack_array8()
            self.assertEqual(value, result)

Notice that the only difference between these functions is the (value, data)
pair and the function.  And there are lots of functions like this in the
DatatypeUnpack class.

Surely there's a better way?  I was thinking something like this:

class DatatypeUnpack2(unittest.TestCase):
    knownvals = { xdmcplib.Unpacker.unpack_card32:
              ( (0,'\x00\x00\x00\x00'), (1,'\x00\x00\x00\x01'),
                (2,'\x00\x00\x00\x02'), (65535,'\x00\x00\xff\xff'),
                (4294967295L,'\xff\xff\xff\xff') ) }

    def testUnpackCard32(self):
        """unpack_card32() should return known result from known valid
input"""
        funct = xdmcplib.Unpacker.unpack_card32
        for value, data in self.knownvals.get(funct):
            instance = funct.im_class(data)
            result = funct(instance)
            self.assertEqual(value, result)

Of course, this is more lines of code than before, but at least all the data
is in one place.

What I'd really like is never to have to write a test function at all: just
update the testcases dictionary and have the class "generate" one test
method for each key, docstrings and all.  Is this possible?  (It involves
metaclasses, doesn't it? *sigh*)

It seems like this would be a common sort of occurrence in a testing
framework, so is there some idiom or pattern I'm missing?  Is there any
other approach? Am I over-engineering?  Should I just forget about this, get
friendly with cut-and-paste, and get on with my life?
--
Francis Avila





More information about the Python-list mailing list