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

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

Я пытаюсь понять, для чего conftest.py файлы conftest.py.

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

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

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

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

Ответ 1

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

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

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

Да, это так.

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

  • Загрузка внешних плагинов: 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, root/mod только "I am 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 его при необходимости.

корень/тесты/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.

Ответ 2

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

Ответ 3

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

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

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

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

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

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

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

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