Problem Statement
I am trying to build unit tests for a function that performs a series of arithmetic operations on the input it receives. The operations are configured outside of the function (in a package constant in this case).
My issue is that I can write tests that pass when they should but either the tests will break if the external configuration changes or the test will be mostly a repetition of the code in the function to be tested.
The two ways I can think of writing the tests are:
A test that "assumes" a specific configuration. The problem is that the test is fragile and will stop working if I change the configuration. (See test_example1 below)
- Create a expected result assuming some operations and applying to the input
- Call the function to test
- Compare expected result with actual returned by the function to test
I can build a test that uses the configuration to calculate an expected result. The problems are, first, the test depends on a configuration constant outside of the function, and second, the code for the test is the very similar to the tested code, which feels wrong. (See test_example2 below)
- Create a expected result processing the input according to the configuration constant
- Call the function to test
- Compare expected result with actual returned by the function to test
Can you help me figure out what is the right way to unit test a function that performs operations configured outside of it?
Sample Code
import unittest
import operator
OPS = {'+':operator.add,
'-':operator.sub}
DIRECTIVES = {'calculated_field':[('+','field1'),
('+','field2')]}
def example(input_dict):
output_dict = {}
for item,calcs in DIRECTIVES.items():
output_dict[item] = 0
for operation, field in calcs:
output_dict[item] = OPS[operation](output_dict[item],input_dict[field])
return output_dict
class TestExample(unittest.TestCase):
item1 = 'field1'
value1 = 10
item2 = 'field2'
value2 = 20
item3 = 'field3'
value3 = 5
def setUp(self):
self.input_dict = {self.item1:self.value1,
self.item2:self.value2,
self.item3:self.value3}
def test_example_option1(self):
expected_result = {'calculated_field':self.value1+self.value2}
actual_result = example(self.input_dict)
self.assertDictEqual(expected_result,actual_result)
def test_example_option2(self):
expected_result = {}
for item,calcs in DIRECTIVES.items():
expected_result[item] = 0
for operation, field in calcs:
expected_result[item] = OPS[operation](expected_result[item],self.input_dict[field])
actual_result = example(self.input_dict)
self.assertDictEqual(expected_result,actual_result)