dimanche 17 mars 2019

Best practices for unit testing in Python - multiple functions apply to same object

I have a bunch of functions which apply to a similar object, for example a Numpy array which represents an n-dimensional box:

# 3-D box parameterized as:
#     box[0] = 3-D min coordinate
#     box[1] = 3-D max coordinate
box = np.array([
    [1, 3, 0],
    [4, 5, 7]
])

Now I have a whole bunch of functions that I want to run on lists of boxes, eg. volumes, intersection, smallest_containing_box, etc. In my mind here is the way I was hoping to set this up:

# list of test functions:
test_funcs = [volume, intersection, smallest_containing_box, ...]
# manually create a bunch of inputs and outputs
test_set_1 = (
    input = [boxA, boxB, ...], # where each of these are np.Array objects
    output = [
        [volA, volB, ...], # floats I calculated manually
        intersection, # np.Array representing the correct intersection
        smallest_containing_box, # etc.
    ]
)
# Create a bunch of these, eg. test_set_2, test_set_3, etc. and bundle them in a list:
test_sets = [test_set_1, ...]
# Now run the set of tests over each of these:
test_results = [[assertEqual(test(t.input), t.output) for test in test_funcs] for t in test_sets]

The reason I want to structure it this way is so that I can create multiple sets of (input, answer) pairs and just run all the tests over each. Unless I'm missing something, the structure of unittest doesn't seem to work well with this approach. Instead, it seems like it wants me to create an individual TestCase object for each pair of function and input, i.e.

class TestCase1(unittest.TestCase):
    def setUp(self):
        self.input = [...]
        self.volume = [volA, volB, ...]
        self.intersection = ...
        # etc.

    def test_volume(self):
        self.assertEqual(volume(self.input), self.volume)

    def test_intersection(self):
        self.assertEqual(intersection(self.input), self.output)

    # etc.

# Repeat this for every test case!?

This seems like a crazy amount of boilerplate. Am I missing something?

Aucun commentaire:

Enregistrer un commentaire