Могу ли я смоделировать тестовый набор в setUpClass? - PullRequest
0 голосов
/ 16 января 2019

Я использую макет декоратора в каждом тестовом случае. Можно ли как-нибудь объединить декоратор с setUpClass?

Мой юнит-тест так же, как:

    class TestCase():
        @mock.patch('some.path.config')
        def test_case_001(self, mock_cfg):
            mock_cfg.return_value = 'value'
            ...

        @mock.patch('some.path.config')
        def test_case_002(self, mock_cfg):
            mock_cfg.return_value = 'value'
            ...
        @mock.patch('some.path.config')
        def test_case_003(self, mock_cfg):
            mock_cfg.return_value = 'value'
            ...

Могу ли я объединить там макет с одним, как:

    class TestCase():
        @mock.patch('some.path.config')
        @classmethod
        def setUpClass(cls, mock_cfg):
            mock_cfg.return_value = 'value'
            pass

        def test_case_001(self):
            pass

        def test_case_002(self):
            pass

        def test_case_003(self):
            pass

Ответы [ 3 ]

0 голосов
/ 27 февраля 2019

используйте метод, подобный этому, должно быть полезно.

class TestDemo(test.TestCase):
    def setUp(self):
        super(TestDemo, self).setUp()
        self.mocks = [(mock.patch('a.methodB',
                                mock.MagicMock(return_value=None)))]
        for single_mock in self.mocks:
            single_mock.start()
            self.addCleanup(single_mock.stop)

0 голосов
/ 27 февраля 2019

Есть разные способы сделать это.Ниже приведены приемы, которые я сейчас использую с python2 и python3.

Предположим, мы собираемся смоделировать функцию с именем get_val для возврата yes:

# data.py

def get_val():
    return 'no'

Я просто буду использовать setUp в демонстрационном коде, но тот же трюк должен работать и с setUpClass.

1.Самый простой способ: использовать макет на тестовом классе

# test_data.py

# mock value is fixed
@patch('data.get_val', MagicMock(return_value='yes'))  # fixed value
class TestFoo(TestCase):
    def setUp(self):
        print(data.get_val())   # no

    def test_case(self):
        print(data.get_val())   # yes

# mock value set by each test case
@patch('data.get_val')
class TestBar(TestCase):
    def setUp(self):
        print(data.get_val())   # no

    def test_case(self, mock_get_val):
        mock_get_val.return_value = 'yes'  # set value in each case
        print(data.get_val())   # yes

Плюсы:

  • Простейшие

Минусы:

  • Цель не смоделирована в setUp
  • Вы можете выбрать либо макет цели с фиксированным значением, либо предоставить значение макета в каждом отдельном тестовом случае.Никакой микс не использует вообще.

2.Самый гибкий способ: запустить макет вручную

# test_data.py

class TestCool(TestCase):
    def setUp(self):
        self.mocks = [patch('data.get_val', MagicMock(return_value='yes'))]  # fixed value
        for mock in self.mocks:
            mock.start()
        print(data.get_val())   # yes

    def tearDown(self):
        for mock in self.mocks:
            mock.stop()

    def test_case(self):
        print(data.get_val())   # yes

    def test_case_cool(self):
        self.mocks[0].return_value = 'cool'  # override the mock only for this case
        print(data.get_val())   # cool

Плюсы:

  • Вы можете получить макеты работ внутри setUp s
  • Вы можете смешать использованиемакет с предварительно заданными фиксированными значениями или предоставление значений макетов в каждом тестовом случае
  • Проще управлять тоннами макетов, поскольку вы можете написать код для управления ими.

Минусы:

  • Пришлось бы написать больше кода для даже простых задач.

Бонусный совет:

Не используйте patch на setUp напрямую,потому что изменение подписи setUp s вызывает жалобу PyCharm на это:

Подпись метода 'TestMockedSetup.setUp ()' не соответствует подписи базового метода в классе 'TestCase'

А если серьезно, макет работает только внутри setUp и в ваших тестовых примерах будет восстановлен как немодированный, что, вероятно, не то, что вам нужно.

0 голосов
/ 16 января 2019

Просто установите макет и используйте self:

class TestName(TestCase):
    @mock.patch('some.path.config')
    def setUp(self, mock_cfg):
        self.mock_cfg = mock_cfg
        self.mock_cfg.return_value = 'value'
        ...

    def test_case_001(self):
        ... # use self.mock_cfg

    def test_case_002(self):
        ... # use self.mock_cfg

    ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...