Persist variable changes between tests in unittest?

Question:

How do I persist changes made within the same object inheriting from TestCase in unitttest?

from unittest import TestCase, main as unittest_main


class TestSimpleFoo(TestCase):
    foo = 'bar'

    def setUp(self):
        pass

    def test_a(self):
        self.assertEqual(self.foo, 'bar')
        self.foo = 'can'

    def test_f(self):
        self.assertEqual(self.foo, 'can')


if __name__ == '__main__':
    unittest_main()

I.e.: I want those two tests above to pass

Asked By: A T

||

Answers:

Couldn’t figure it out; so ended up hacking it out with multiple non test_ prefixed functions:

def test_password_credentials_grant(self):
    for user in self.user_mocks:
        self.register(user)
        self.login(user)
        self.access_token(user, self.assertEqual)  # Ensures access_token is generated+valid
        self.logout(user)
        self.access_token(user, self.assertNotEqual)  # Ensures access_token is now invalid
        self.unregister(user)
Answered By: A T

I like your own answer for the simplicity of it, but if you want to keep distinct unit tests:

Apparently unittest runs separate tests with fresh instances of the TestCase. Well, just bind the objects to be persisted to something else but self. For example:

from unittest import TestCase, main as unittest_main


class TestSimpleFoo(TestCase):

    def setUp(self):
        pass

    def test_a(self):
        TestSimpleFoo.foo = 'can'

    def test_f(self):
        self.assertEqual(TestSimpleFoo.foo, 'can')


if __name__ == '__main__':
    unittest_main()

You might be interesed in setUpClass and tearDownClass too:
https://docs.python.org/3/library/unittest.html#setupclass-and-teardownclass

Also take care about the execution order of your unit tests:
https://docs.python.org/2/library/unittest.html#unittest.TestLoader.sortTestMethodsUsing

Answered By: Matthias

As some comments have echoed, structuring your tests in this manner is probably a design flaw in the tests themselves and you should consider restructuring them. However, if you want to do this and rely on the fact that the test runner you are using executes them in an alphabetical (seemingly) order then I suggest the following.

Similar to what @Matthias was saying but I would do one thing differently for the cases where you may decide to inherit from the class at a later date.

from unittest import TestCase, main as unittest_main


class TestSimpleFoo(TestCase):
    foo = 'bar'

    def setUp(self):
        pass

    def test_a(self):
        self.assertEqual(self.__class__.foo, 'bar')
        self.__class__.foo = 'can'

    def test_f(self):
        self.assertEqual(self.__class__.foo, 'can')


if __name__ == '__main__':
    unittest_main()

The difference between this answer and @Matthias’s answer you accepted is the explicit declaration of the class versus the lookup of said class reference.

TestSimpleFoo vs self.__class__

I prefer the dynamicness so I can inherit the tests later and run both test classes back to back and not have any cross over between the two. Because if you would choose to inherit from this class, explicitly naming the class reference would cause both test classes to run against that reference rather than their own respective classes.

Answered By: rdp