В Pytest, для чего нужны файлы conftest.py?

218

Я недавно обнаружил pytest. Кажется, отлично. Тем не менее, я чувствую, что документация может быть лучше.

Я пытаюсь понять, для каких conftest.pyфайлов они предназначены.

В моем (в настоящее время небольшом) наборе тестов у меня есть один conftest.pyфайл в корне проекта. Я использую его для определения приборов, которые я добавляю в свои тесты.

У меня есть два вопроса:

  1. Это правильное использование conftest.py? У этого есть другое использование?
  2. Могу ли я иметь более одного conftest.pyфайла? Когда бы я хотел это сделать? Примеры будут оценены.

В более общем смысле, как бы вы определили цель и правильное использование conftest.pyфайлов в наборе тестов py.test?

Авив Кон
источник
9
Вы меня наIt seems great. However, I feel the documentation could be better.
user9074332
7
Да, документация может быть намного лучше. Я искал всю документацию по pytest conftest.pyи, хотя есть много ссылок на то, чтобы делать это или делать это с помощью файла conftest, нигде в документации это не указывает на то, что когда pytest проверяет обнаружение, все найденные файлы conftest.py (в пределах структура каталога, над которой выполняется обнаружение тестов) будет запущена на этапе сбора тестов (до запуска любых тестов). Пришлось самому разобраться в этом с помощью экспериментов.
Даниэль Голдфарб

Ответы:

290

Это правильное использование conftest.py?

Да, это так. Светильники являются потенциальным и широко используемым conftest.py. Определенные вами приборы будут доступны всем тестам в вашем наборе тестов. Однако определение приборов в корневом каталоге conftest.pyможет оказаться бесполезным, и это приведет к замедлению тестирования, если такие приборы не используются всеми тестами.

У этого есть другое использование?

Да, это так.

  • Приспособления : Определите приспособления для статических данных, используемых тестами. Эти данные могут быть доступны для всех тестов в наборе, если не указано иное. Это могут быть как данные, так и помощники модулей, которые будут переданы во все тесты.

  • Загрузка внешних плагинов : conftest.pyиспользуется для импорта внешних плагинов или модулей. Определив следующую глобальную переменную, pytest загрузит модуль и сделает его доступным для его тестирования. Плагины - это, как правило, файлы, определенные в вашем проекте или других модулях, которые могут понадобиться в ваших тестах. Вы также можете загрузить набор предопределенных плагинов, как описано здесь .

    pytest_plugins = "someapp.someplugin"

  • Хуки : Вы можете указать хуки, такие как методы настройки и демонтажа, и многое другое для улучшения ваших тестов. Для набора доступных хуков, прочитайте здесь . Пример:

    def pytest_runtest_setup(item):
         """ called before ``pytest_runtest_call(item). """
         #do some stuff`
  • Проверка корневого пути : это немного скрытая функция. Определяя conftest.pyв своем корневом пути, вы будете pytestраспознавать модули приложения без указания PYTHONPATH. В фоновом режиме py.test изменяет ваш файл sys.path, включая все подмодули, найденные в корневом пути.

Могу ли я иметь более одного файла conftest.py?

Да, вы можете, и это настоятельно рекомендуется, если ваша тестовая структура несколько сложна. conftest.pyфайлы имеют область каталогов. Поэтому создание целевых приспособлений и помощников является хорошей практикой.

Когда бы я хотел это сделать? Примеры будут оценены.

Могут подойти несколько случаев:

Создание набора инструментов или хуков для определенной группы тестов.

корень / мода / conftest.py

def pytest_runtest_setup(item):
    print("I am mod")
    #do some stuff


test root/mod2/test.py will NOT produce "I am mod"

Загрузка набора светильников для некоторых тестов, но не для других.

корень / мода / conftest.py

@pytest.fixture()
def fixture():
    return "some stuff"

корень / mod 2 / conftest.py

@pytest.fixture()
def fixture():
    return "some other stuff"

корень / mod 2 / test.py

def test(fixture):
    print(fixture)

Напечатает «некоторые другие вещи».

Перекрывающие крючки наследуются от корня conftest.py.

корень / мода / conftest.py

def pytest_runtest_setup(item):
    print("I am mod")
    #do some stuff

корень / conftest.py

def pytest_runtest_setup(item):
    print("I am root")
    #do some stuff

При запуске любого теста внутри root/mod, печатается только «Я мод».

Вы можете прочитать больше о conftest.py здесь .

РЕДАКТИРОВАТЬ:

Что если мне понадобятся простые старые вспомогательные функции для вызова из нескольких тестов в разных модулях - будут ли они мне доступны, если я положу их в файл conftest.py? Или я должен просто поместить их в модуль helpers.py и импортировать и использовать в своих тестовых модулях?

Вы можете использовать, conftest.pyчтобы определить ваши помощники. Тем не менее, вы должны следовать обычной практике. Помощники могут быть использованы в качестве светильников, по крайней мере, в pytest. Например, в моих тестах у меня есть вспомогательный помощник redis, который я добавляю в свои тесты таким образом.

корень / помощник / Redis / redis.py

@pytest.fixture
def mock_redis():
    return MockRedis()

корень / тесты / материал / conftest.py

pytest_plugin="helper.redis.redis"

корень / тесты / материал / test.py

def test(mock_redis):
    print(mock_redis.get('stuff'))

Это будет тестовый модуль, который вы можете свободно импортировать в свои тесты. Обратите внимание, что вы могли бы назвать, redis.pyкак conftest.pyбудто ваш модуль redisсодержит больше тестов. Однако такая практика не рекомендуется из-за двусмысленности.

Если вы хотите использовать conftest.py, вы можете просто поместить этот помощник в свой корень conftest.pyи внедрить его при необходимости.

корень / тесты / conftest.py

@pytest.fixture
def mock_redis():
    return MockRedis()

корень / тесты / материал / test.py

def test(mock_redis):
    print(mock_redis.get(stuff))

Еще одна вещь, которую вы можете сделать, это написать устанавливаемый плагин. В этом случае ваш помощник может быть написан где угодно, но ему нужно определить точку входа, которая будет установлена ​​в вашей и других потенциальных тестовых средах. Смотрите это .

Если вы не хотите использовать фиксаторы, вы, конечно, можете определить простого помощника и просто использовать обычный старый импорт везде, где это необходимо.

корень / тесты / помощник / redis.py

class MockRedis():
    # stuff

корень / тесты / материал / test.py

from helper.redis import MockRedis

def test():
    print(MockRedis().get(stuff))

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

корень / тесты / помощник / __ init__.py

from .redis import MockRedis

Или просто добавив вспомогательный модуль к вашему PYTHONPATH.

Симона Зандара
источник
Я сталкиваюсь с ситуацией, в которой мой первый модуль модульного тестирования, test_aaaaa.pyна самом деле пытается запустить до завершения установки прибора conftest.py. Есть мысли о том, почему это может происходить?
user9074332
Без conftest.py ваш путь к тестовому корневому каталогу не будет добавлен в sys.path, и вы увидите ошибки типа «ModuleNotFoundError: нет модуля с именем« foobar »».
Кейл Суини
11

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

Яростная утка
источник
10

Я использую conftest.pyфайл для определения приборов, которые я добавляю в свои тесты, это правильное использование conftest.py?

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

У этого есть другое использование?

Да , прибор - это функция, которая запускается pytestдо, а иногда и после, реальных тестовых функций. Код в приборе может делать все, что вы хотите. Например, прибор может использоваться для получения набора данных для работы тестов, или прибор также может использоваться для приведения системы в известное состояние перед запуском теста.

Могу ли я иметь более одного conftest.pyфайла? Когда бы я хотел это сделать?

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

Во-вторых, да , у вас могут быть другие conftest.pyфайлы в подкаталогах каталога верхних тестов. Если вы это сделаете, приборы, определенные в этих conftest.pyфайлах более низкого уровня, будут доступны для тестов в этом каталоге и подкаталогах.

Наконец, размещение осветителей в conftest.pyфайле в тестовом корне сделает их доступными во всех тестовых файлах.

lmiguelvargasf
источник