Персистентная переменная изменяется между тестами в unittest?

Как сохранить изменения, сделанные внутри одного объекта, наследующего от TestCase в 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: Я хочу, чтобы эти два теста выше проходили

Ответы

Ответ 1

Как уже отмечалось в некоторых комментариях, структурирование ваших тестов таким образом, вероятно, является конструктивным недостатком самих тестов, и вы должны рассмотреть возможность их реструктуризации. Однако, если вы хотите сделать это и полагаться на то, что используемый вами тестовый бегущий выполняет их в алфавитном порядке (по-видимому), я предлагаю следующее.

Подобно тому, что говорил @Matthias, но я бы сделал одну вещь по-разному в тех случаях, когда вы можете решить наследовать от класса на более позднюю дату.

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()

Разница между этим ответом и ответом @Matthias на то, что вы приняли, - это явное объявление класса по сравнению с поиском указанной ссылки на класс.

TestSimpleFoo vs self.__class__

Я предпочитаю динамику, поэтому я могу наследовать тесты позже и запускать оба тестовых класса назад и не перекрещиваться между ними. Поскольку, если вы захотите наследовать от этого класса, явное назначение ссылки на класс приведет к тому, что оба тестовых класса будут выполняться против этой ссылки, а не их собственные соответствующие классы.

Ответ 2

Мне нравится ваш собственный ответ на простоту, но если вы хотите сохранить отдельные модульные тесты:

Очевидно, unittest запускает отдельные тесты со свежими экземплярами TestCase. Ну, просто привяжите объекты к чему-то еще, кроме себя. Например:

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()

Вы можете быть заинтересованы в setUpClass и tearDownClass: https://docs.python.org/3/library/unittest.html#setupclass-and-teardownclass

Также соблюдайте порядок выполнения ваших модульных тестов: https://docs.python.org/2/library/unittest.html#unittest.TestLoader.sortTestMethodsUsing

Ответ 3

Не мог понять это; так что в итоге он взломал несколько префиксов, отличных от test_:

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)