1

I am using setUp to create a new object from a class I created. It is my understanding that this function will be executed before each test in the test case, and that this should result in new objects being created for each test. It seems that this is not what is happening; at least not in my tests.

Here is my class:

class Entity:
    def __init__(self, entities = []):
        self.entities = entities

    def add(self, entity: str):
        if entity not in self.entities:
            self.entities.append(entity)

And here are the corresponding tests:

import unittest
from entity import Entity

class EntityTestCase(unittest.TestCase):
    def setUp(self):
        self.entity = Entity()
        print("Starting Entites = {}".format(self.entity.entities))

    def testA(self):
        self.entity.add("Foo")
        self.assertEqual(self.entity.entities, ["Foo"])

    def testB(self):
        self.entity.add("Bar")
        self.assertEqual(self.entity.entities, ["Bar"])

if __name__ == '__main__':
    unittest.main()

I would expect that testA and testB would start with new Entity objects. That is, I would expect Entity.entities to be a brand new list for each test.

I am running my tests with python -m unittest discover -v which results in the following output:

$ python -m unittest discover -v
testA (test_entity.EntityTestCase) ... Starting Entites = []
ok
testB (test_entity.EntityTestCase) ... Starting Entites = ['Foo']
FAIL

======================================================================
FAIL: testB (test_entity.EntityTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/julioguzman/Sites/Foobar/test_entity.py", line 15, in testB
    self.assertEqual(self.entity.entities, ["Bar"])
AssertionError: Lists differ: ['Foo', 'Bar'] != ['Bar']

First differing element 0:
'Foo'
'Bar'

First list contains 1 additional elements.
First extra element 1:
'Bar'

- ['Foo', 'Bar']
+ ['Bar']

----------------------------------------------------------------------
Ran 2 tests in 0.001s

FAILED (failures=1)

As you can see, testB starts with the data from testA. This is not the desired behavior, although it may be the intended one.

How do I ensure that my objects are "clean" for each test? Why is this happening?

Julio
  • 2,261
  • 4
  • 30
  • 56

1 Answers1

2

You have

class Entity:
    def __init__(self, entities = []):
        self.entities = entities

Where the default argument is instantiated once and thus resulting in this common issue

Simply modify the __init__ to use a surrogate value and assign a brand new list if so:

class Entity:
    def __init__(self, entities=NotImplemented):
        if entities is NotImplemented:
            self.entities = []
        else:
            self.entities = entities

As an aside, this is one reason why unittests are written: they also test whether the class was created correctly with the expected behavior. It was not an issue with your test when the setUp clearly showed that it created a brand new object - the fault lies with the implementation where it did something unexpected.

metatoaster
  • 17,419
  • 5
  • 55
  • 66