0

I want to test a simple class A:

class A:
    _cache = None

    def func(self):
        if not A._cache:
            A._cache = 'Get value from some service'


class TestA:
    def test_cache_after_func(self):
        a = A()
        a.func()
        assert A._cache is not None

    def test_cache_empty(self):
        a = A()
        assert A._cache is None

These two tests pass when run separately from VSCode. But when they are run together then second test fails because the first one already has modified the _cache field.

How to run these tests isolated without affecting one another? (I would appreciate examples both for unittest and pytest if they differ)

elshev
  • 1,164
  • 3
  • 16
  • 30
  • Class variables are shared across all objects while instance variables are for data unique to each instance. Instance variable overrides the Class variables having same name which can accidentally introduce bugs or surprising behaviour in our code and are therefore considered to be a code smell. I guess your best option is to use something line [pytest-dependency](https://pytest-dependency.readthedocs.io/en/latest/usage.html), as there is no way to disentangle in your current design. – Cpt.Hook Jun 21 '23 at 07:52
  • So, depending on what you want to do here, it might be a good idea to either re-think your design or your testing approach. – Cpt.Hook Jun 21 '23 at 07:53
  • 1
    Can you clarify the intention behind designing class `A` this way? – Oluwafemi Sule Jun 21 '23 at 07:54
  • @OluwafemiSule, let's say I need a static field shared between instances of the class. Actually, this is a conceptual question about test run isolation. – elshev Jun 21 '23 at 08:01
  • Maybe a [singleton](https://stackoverflow.com/questions/6760685/creating-a-singleton-in-python) would be the right concept here. The singleton container can hold the shared information and manage the access, while your class instances just depend on the singeltons state... – Cpt.Hook Jun 21 '23 at 08:13

1 Answers1

0

Method setUp() of the class unittest.TestCase

You can use the module unittest and the method setUp() of the class unittest.TestCase to set to None the class variable _cache.

About the method setUp() doumentation reports this sentence:

The setUp() method allows you to define instructions that will be executed before each test method.

Your code could be inserted in a subclass of the unittest.TestCase, defining a setUp() method which init the class variable _cache. So your code could become as following:

import unittest

class A:
    _cache = None

    def func(self):
        if not A._cache:
            A._cache = 'Get value from some service'


class MyTestCase(unittest.TestCase):

    def setUp(self) -> None:
        A._cache = None

    def test_cache_after_func(self):
        a = A()
        a.func()
        assert A._cache is not None

    def test_cache_empty(self):
        a = A()
        assert A._cache is None


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

If you execute the previous code the 2 tests pass, while if you remove the setUp() method, the second one fails.

This post also adds other explanations about methods setUp() and tearDown() with other useful links.

frankfalse
  • 1,553
  • 1
  • 4
  • 17