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.