Is there a minimal style for unittests in Python?

I wonder what methods people use to simplify the "size" of the code used for unit testing. For example, I tried to marshal a class object and test a marshal object (but this assumes that the marshal is working correctly).

Consider the class

import unittest
class Nums(object):
    def __init__(self, n1_, n2_, n3_):
        self.n1, self.n2, self.n3 = n1_, n2_, n3_
def marshal(self):
    return "n1 %g, n2 %g, n3 %g"%(self.n1,self.n2,self.n3)

and then tests based on marshaling, list-based and normal

class NumsTests(unittest.TestCase):
    def setUp(self):
        self.nu = Nums(10,20,30)
    def test_init1(self):
        self.assertEquals(self.nu.marshal(),"n1 %g, n2 %g, n3 %g"%(10,20,30))
    def test_init2(self):
        self.assertEquals([self.nu.n1,self.nu.n2,self.nu.n3],[10,21,31])
    def test_init3(self):
        self.assertEquals(self.nu.n1,10)
        self.assertEquals(self.nu.n2,21)
        self.assertEquals(self.nu.n3,31)

which give the following errors (since 20! = 21 and 30! = 31, my test has poor initialization or the test conditions are incorrect)

AssertionError: 'n1 10, n2 20, n3 30' != 'n1 10, n2 21, n3 31'

AssertionError: [10, 20, 30] != [10, 21, 31]

AssertionError: 20 != 21

The first and second error messages are hard to understand (since you need to parse a line or a list). However, the 3rd method quickly explodes in the amount of code used to test complex objects.

? , ?

[ test_marshal marshal]

+5
2

, marshal(). , , , . " " , , , , , .

, , Eli:

class MyTestCase(unittest.TestCase):
    def assertFieldsEqual(self, obj, expectedFieldValDict):
        for fieldName, fieldVal in expectedFieldValDict.items():
            self.assertFieldEqual(obj, fieldName, fieldVal)
    def assertFieldEqual(self, obj, fieldName, expectedFieldVal):
        actualFieldVal = getattr(obj, fieldName)
        if expectedFieldVal != actualFieldVal:
            msg = "Field %r doesn't match: expected %r, actual %r" % \
                (fieldName, expectedFieldVal, actualFieldVal)
            self.fail(msg)

class NumsTests(MyTestCase):
    def setUp(self):
        self.initFields = {'n1': 10, 'n2': 20, 'n3': 30}
        self.nums = Nums(**initFields)
    def test_init(self):
        self.assertFieldsEqual(self.nums, self.initFields)

" ," , ", ! , :

  • assertFieldsEqual assertFieldEqual , , .
  • , .

, :

def test_marshal(self):
    expected = '...'
    self.assertEqual(expected, self.nums.marshal())

, , . Python 2.7, .

+2

, , . , test_marshal, ( , , ), , unit test. , , -

import unittest

class Nums(object):
    FORMAT = "n1 %g, n2 %g, n3 %g"  # make this a variable for easy testing

    def __init__(self, n1, n2, n3):
        self.n1, self.n2, self.n3 = n1, n2, n3  # no underscores necessary

    def test_marshal(self):
        return self.FORMAT % (self.n1, self.n2, self.n3)


class NumsTests(unittest.TestCase):
    def setUp(self):
        self.nums = [10, 20, 30]    # make a param list variable to avoid duplication
        self.nu = Nums(*self.nums)  # Python "apply" syntax
        self.nu_nums = [self.nu.n1, self.nu.n2, self.nu.n3]  # we'll use this repeatedly

    def test_init1(self):
        self.assertEquals(self.nu.test_marshal(), self.nu.FORMAT % self.nums )

    def test_init2(self):
        self.assertEquals(self.nums, self.nu_nums)

    def test_init3(self):
        for reference, test in zip(self.nums, self.nu_nums):
            self.assertEquals(reference, test)

. http://docs.python.org/library/functions.html#apply apply, .

, , , , , .

, , , , . , , - , , , , . , -, , , , , , , - :

class NumsTests(unittest.TestCase):
    def setUp(self):
        self.nums = {"n1": 10, "n2": 20, "n3": 30}  # use a dict, not a list
        self.nu = Nums(**self.nums)                 # same Python "apply" syntax

    # test_init1 and test_init2 omitted for space

    def test_init3(self):
        for attr,val in self.nums.items():
            self.assertEqual([attr, val], [attr, getattr(self.nu, val)])

- , ,

AssertionError: ["n1", 10] != ["n1", 11]

, , , , , . - , test_init3 , Nums.

, getattr , __init__ , num, n1, n1_ .. __ dict__, .

+3

All Articles