pytest: как использовать метку для ввода осветителя? - PullRequest
0 голосов
/ 30 мая 2018

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

Как я могу использовать метку, чтобы требовать приспособления в pytest?Глядя на документы, кажется, что я хочу подключиться к чему-то вроде pytest_collection_modifyitems, проверить соответствующую отметку на каждом элементе с помощью Item.iter_markers, а затем каким-то образом обновить список приборов.Однако, читая код, я не могу понять, как именно запустить эту настройку прибора.

Вот упрощенный пример того, как выглядит данный прибор:

@pytest.fixture
def mocks(mocker):
    ret_val = 10
    mocker.patch('path.to.patch', return_value=ret_val)
    return ret_val

Вот что пользователь может сделать, чтобы настроить макеты сейчас:

def test_mocks(mocks):
    # 'path.to.patch' will be mocked in this test
    # ... test code ...

Но вот как мог бы выглядеть тест, если бы прибор можно было запустить с помощью метки:

@pytest.mark.mocks
def test_mocks():
    # 'path.to.patch' will be mocked in this test, too
    # ... test code ...

Ответы [ 2 ]

0 голосов
/ 30 мая 2018

Я смог реализовать это, используя pytest_collection_modifyitems крючок для настройки списка приборов на тестовом элементе после сбора:

@pytest.hookimpl(trylast=True)
def pytest_collection_modifyitems(items):
    '''
    Check if any tests are marked to use the mock.
    '''
    for item in items:
        # Note that `get_marker` has been superceded by `get_closest_marker`
        # in the development version of pytest
        if item.get_marker('mocks'):
            item.fixturenames.append('mocks')

Настройка списка Item.fixturenamesпосле того, как появится коллекция, чтобы запустить настройку прибора, как я и надеялся.

Если вам не нужно использовать пользовательскую метку, рекомендация @ hoefling использовать встроенную метку usefixtures будетхорошее решение тоже.

0 голосов
/ 30 мая 2018

Используйте маркер usefixtures:

# conftest.py
import pytest

@pytest.fixture
def mocks(mocker):
    mocker.patch('os.path.isdir', return_value=True)

# test_me.py
import os
import pytest

@pytest.mark.usefixtures('mocks')
def test_mocks():
    assert os.path.isdir('/this/is/definitely/not/a/dir')

Возможна также передача нескольких приборов:

@pytest.mark.usefixtures('mocks', 'my_other_fixture', 'etc')

Однако есть предостережение: приспособление mocks в вашем кодевозвращает значение ret_val.При передаче прибора через аргументы тестовой функции это значение возвращается в аргументе mocks arg;когда вы используете маркеры, у вас больше нет аргумента, поэтому вы не сможете использовать это значение.Если вам понадобится фиктивное значение, передайте прибор в аргументы тестовой функции.Есть и другие способы, которые можно себе представить, например, передача ret_val через кеш, однако полученный код будет более сложным и менее читабельным, поэтому я бы не стал беспокоиться.

...