Django Unit Tests – Changes to self properties are persisting from test to test

Question:

I have a test class that has a setup like this. We import a dictionary from a test_helpers file that has some default data. The data is set as FORM_DATA['value_A'] = 0 and FORM_DATA['value_B'] = 1000000 from the start.

Whether I set FORM_DATA to a self.form_data value, or assign it to a variable in each test, doesn’t matter. The 2nd test seems to persist the dictionary changes from the 1st test, which is not ideal for testing.

I added a bunch of print debug statements to show what is happening. Even in the setUp() for the 2nd test, it shows the values from the previous test! What is happening here? Why can’t the dictionary self.form_data be the default imported data every time I have a new test?

from test_helpers import FORM_DATA

class TestBaselineScenarios(TestCase):
    @classmethod
    def setUpClass(cls):
        super(TestBaselineScenarios, cls).setUpClass()
        long_running_data_setup()

    def setUp(self):
        self.form_data = FORM_DATA
        print("setUp", self.form_data['value_A'], self.form_data['value_B'])

    def test_one(self):
        print("1")
        print(self.form_data['value_A'], self.form_data['value_B'])
        self.form_data['value_A'] = 25000
        self.form_data['value_B'] = 700000
        print("2")
        print(self.form_data['value_A'], self.form_data['value_B'])
        simulation = test_helpers.create_simulation(form_data=self.form_data)
        simulation.run()
        self.assertEqual(0.8416667, round(simulation.success_rate(), 7))

    def test_two(self):
        print("3")
        print(self.form_data['value_A'], self.form_data['value_B'])
        self.form_data['value_A'] = 10000
        print("4")
        print(self.form_data['value_A'], self.form_data['value_B'])
        simulation = test_helpers.create_simulation(form_data=self.form_data)
        simulation.run()
        self.assertEqual(0.9916667, round(simulation.success_rate(), 7))
setUp 0 1000000
1
0 1000000
2
25000 700000


setUp 25000 700000
3
25000 700000
4
10000 700000
Asked By: Lauren Boland

||

Answers:

When you run this code:

self.form_data = FORM_DATA

you’re not actually copying the contents of FORM_DATA, just storing a reference to it.
So, when you run self.form_data['value_A'] = 25000, you’re also changing FORM_DATA.

Next time you run setUp, it’s just assigning the same reference to the modified FORM_DATA back into self.form_data.

Try doing a copy of FORM_DATA instead.

Python has a couple of ways to create copies of things. Assuming FORM_DATA is a dict, the simplest is to call dict.copy. If it’s more complex, you could also use the built-in copy library to create a shallow copy.

Change your setUp function to:

    def setUp(self):
        self.form_data = FORM_DATA.copy()
        print("setUp", self.form_data['value_A'], self.form_data['value_B'])
Answered By: kibibu