Каковы функциональные различия в этих 3 приспособлениях? - PullRequest
0 голосов
/ 18 января 2019

Я относительно новичок в модульном тестировании в стиле Pytest и пытаюсь узнать больше о приспособлениях Pytest. Я не передаю аргумент области видимости устройству, поэтому я знаю, что область действия - это «функция». Есть ли функциональные различия в этих 3 стилях простых приборов? Почему один подход предпочтительнее других?

@pytest.fixture()
@patch('a.b.c.structlog.get_logger')
def fixture_classQ(mock_log):
    handler = MagicMock(spec=WidgetHandler)
    return ClassQ(handler)
@pytest.fixture()
def fixture_classQ():
    with patch('a.b.c.structlog.get_logger'):
        handler = MagicMock(spec=WidgetHandler)
        return ClassQ(handler)
@pytest.yield_fixture()
def fixture_classQ():
    with patch('a.b.c.structlog.get_logger'):
        handler = MagicMock(spec=WidgetHandler)
        yield ClassQ(handler)

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

def test_classQ_str(fixture_classQ):
    assert str(fixture_classQ) == "This is ClassQ"

Спасибо.

1 Ответ

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

крепеж 1

Начиная с первого, это создает фиксированный файл данных. Макет (вводит в заблуждение) только жив во время функции фикстуры, потому что он использует return.

Для того, что примерно произойдет для этого:

  • Pytest замечает, что ваш прибор используется для тестовой функции
  • вызывает функцию
    • фиктивный декоратор запускает патч
    • фиктивный декоратор вызывает вашу фактическую функцию (которая возвращает значение)
    • фиктивный декоратор отменяет патч
  • pytest замечает, что это был не генератор, и это ценность вашего прибора

крепеж 2

второй по поведению идентичен первому, за исключением того, что вместо декоратора используется форма диспетчера контекста mock. лично мне не нравится форма декоратора, но это только я: D

крепеж 3

(сначала, прежде чем продолжить, pytest.yield_fixture является устаревшим псевдонимом для pytest.fixture - вы можете просто использовать @pytest.fixture)

Третий делает что-то другое! Патч жив на протяжении всего теста, потому что он «уступил» во время фиксации. Это своего рода способ создать установку + демонтаж все в одном. Вот примерно исполнение здесь

  • Pytest замечает, что ваш прибор используется для тестовой функции
  • pytest вызывает функцию прибора
    • , поскольку он является генератором, он немедленно возвращается без выполнения кода
  • pytest замечает, что это генератор, вызывает next(...) на нем
    • это заставляет код выполняться до yield и затем "останавливаться". Вы можете думать об этом как о совместной подпрограмме
    • __enter__ из mock называется активация патча
    • значение, которое yield ed используется в качестве значения прибора
  • pytest затем выполняет вашу тестовую функцию
  • pytest затем снова вызывает next(...) на генераторе, чтобы истощить прибор
    • это __exit__ s с оператором, отмена патча

какой выбрать?

лучший ответ это зависит . Поскольку 1 и 2 функционально эквивалентны, это зависит от личных предпочтений. Выберите 3. Если вам нужно, чтобы патч был активным на протяжении всего теста. И не используйте pytest.yield_fixture, просто используйте pytest.fixture.

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