Class vs Instance attribute in unit test

Consider this example:

class TestProduct(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.list_a = []
    
    def setUp(self):
        self.list_b = []

    def test_one(self):
        self.assertFalse(self.list_b)
        self.list_a.append(1)

    def test_two(self):
        self.assertFalse(self.list_a)
        self.list_b.append(1)

test_two will succeed if it runs before test_one, because class attribute list_a will still be empty. But if it runs after test_one, it will fail because test_one appends a value to the shared class attribute.

test_one, on the other hand, will always pass because even if test_two runs first, because test_one sees a fresh empty list created by setUp immediately before test_one is called, not the list that test_two modified.

setUp is called before every instance method is called. setUpClass is only called once after the class is defined, but before any test is called.

In your example, it won't matter which you use if Product instances are immutable or no test method modifies the instance, because every test will see the same value whether it is defined in setUp or setUpClass. But when a shared Product instance is feasible, setUpClass is more efficient than recreating the same mutable value before every test.


BTW the correct names for class and instance initialization methods are:

class TestProduct(unittest.TestCase):
    
    @classmethod
    def setUpClass(cls):
        cls.product = Product("book", 30)

    def setUp(self):
        self.product = Product("book", 30)

The difference in that setUp will be invoked for each test method in TestProduct. It is intended to reset values of objects which could be changed by some tests. On the other hand, setUpClass is only invoked once before any test in TestProduct. It is intended for costly initialization of objects that are never changed in any test.