1

I'm writing some unit tests for which I have some preparation to do before every test, and which I should undo after each test. So I'm using setUp to prepare them, using a list to list the actions I've performed, and in the tearDown, I undo the operations listed in said list and clear the list doing so.

But when I reach the following test, the list is not in the same state as tearDown left it, but at the state previous setUp left it. And it feels weird. Am I doing something wrong here?

Here is an short example, without my business code:

class MyTest(TestCase):
    val = []

    def setUp(self):
        super().setUp()
        print("before setup, val = {}".format(self.val))

        self.val.append("AAA")

        print("after setup: val = {}".format(self.val))

    def tearDown(self):
        super().tearDown()
        print("before teardown, val = {}".format(self.val))

        self.val = []  # or whatever

        print("after teardown, val = {}".format(self.val))

    def test_one(self):
        assert True

    def test_two(self):
        assert True

Will return

before start, val = []
after setup: val = ['AAA']
before teardown, val = ['AAA']
after teardown, val = []
.
before start, val = ['AAA']  # <- why is this not []??
after setup: val = ['AAA', 'AAA']
before teardown, val = ['AAA', 'AAA']
after teardown, val = []
.

Shouldn't the setUp from the second test find .val == []? The value seem to have been unaltered by previous tearDown, I don't know why. Any thoughts?

BriceP
  • 508
  • 2
  • 13

2 Answers2

2

Replace self.val with MyTest.val. val is a class-level variable, not an object-level variable. An alternative would be to initialize self.val within setUp instead of making it a class-level variable.

J. Owens
  • 832
  • 7
  • 9
1

val is a class attribute. When you do:

self.val.append("AAA")

This modifies the class version of val. However when you do:

self.val = []

You create an instance attribute named val and set it to an empty list. What you really want to do here is:

self.val[:] = []

This will modify the mutable class attribute val.

Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
  • Well thanks! I understand my mistake. I'll probably make my intention more clear by either creating explicitely the instance attribute or use the class' one with MyClass.val, depending on the refactoring I'll have to do on my code (I don't really like the readability of self.val[:]) – BriceP Mar 30 '18 at 17:11