Как установить динамические параметры по умолчанию для py.test?

У меня есть фреймворк, который работает под py.test. py.test может генерировать отчеты о красоте с параметрами --html и --junitxml. Но клиенты, которые используют мой фреймворк, не всегда вводят эти параметры в командную строку, где они используют py.test. Я хочу, чтобы py.test генерировал отчеты всегда, когда py.test используется с моей платформой. И я хочу поставить эти отчеты с папкой журнала. Поэтому мне нужно сгенерировать путь для отчета во время выполнения. Могу ли я сделать это с помощью светильников? Или, может быть, с помощью плагина API?

5 ответов

Решение

Прежде всего, если вы хотите неявно добавить аргументы командной строки в pytest, вы можете использовать pytest.ini помещены в корневой каталог тестов с addopts значение конфигурации:

[pytest]
addopts=--verbose --junit-xml=/tmp/myreport.xml  # etc

Конечно, если вы хотите динамически рассчитать каталог для хранения отчетов, то вы не можете поместить его в конфигурацию, и вам нужно будет расширить pytest, Лучшее место было бы pytest_configure крюк. Пример:

# conftest.py
import tempfile
import pytest
from _pytest.junitxml import LogXML


@pytest.hookimpl(tryfirst=True)
def pytest_configure(config):
    if config.option.xmlpath:  # was passed via config or command line
        return  # let pytest handle it
    if not hasattr(config, 'slaveinput'):
        with tempfile.NamedTemporaryFile(suffix='.xml') as tmpfile:
            xmlpath = tmpfile.name
            config._xml = LogXML(xmlpath, config.option.junitprefix, config.getini('junit_suite_name'))
            config.pluginmanager.register(config._xml)

Если вы удалите первый if блок, то pytest будет полностью игнорировать --junit-xml аргумент передается через командную строку или в addopts значение в конфиг.

Пример выполнения:

$ pytest
=================================== test session starts ====================================
platform darwin -- Python 3.6.3, pytest-3.3.1, py-1.5.2, pluggy-0.6.0
rootdir: /Users/hoefling/projects/private/stackru/so-48320357, inifile:
plugins: forked-0.2, asyncio-0.8.0, xdist-1.22.0, mock-1.6.3, hypothesis-3.44.4
collected 1 item

test_spam.py .                                                                        [100%]

--- generated xml file: /var/folders/_y/2qk6029j4c7bwv0ddk3p96r00000gn/T/tmp1tleknm3.xml ---
================================ 1 passed in 0.01 seconds ==================================

Отчет xml теперь помещается в временный файл.

Достаточно поместить это в conftest.py:

def pytest_configure(config):
    if config.option.xmlpath is None:
        config.option.xmlpath = get_custom_xml_path() # implement this

Принятый ответ, вероятно, немного сложнее, чем необходимо для большинства людей, по нескольким причинам:

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

Просто чтобы все было понятно, pytest используетargparseи этоargparse.Namespaceобъект. Затем, если вы хотите имитировать параметр командной строки какpytest ... --docker-compose-remove-volumes, вы можете напрямую отнести опцию кrequest.config.option(потому что преобразуется вdocker_compose_remove_volumesмодулем argparse).

В этом примере инвертируется параметр по умолчанию для--docker-compose-remove-volumesчто неверно. Но позвольте вам включить его обратно, предоставив--keep-containersвариант pytest.

      def pytest_addoption(parser):
    parser.addoption("--keep-containers", action="store_true", default=False, 
        help="Keeps docker-compose on failure.")

@pytest.fixture(scope='session', autouse=True)
def load_env(request):
    is_to_keep_container = request.config.getoption("--keep-containers")

    if not is_to_keep_container:
        request.config.option.docker_compose_remove_volumes = True

Настройте файл pytest.ini с параметрами:

# content of pytest.ini
[pytest]
addopts = --html=report.html --self-contained-html
;addopts = -vv -rw --html=./results/report.html --self-contained-html

Ответ @hoefling отлично сработал для меня в conftest.py. код выглядит там проще.

def pytest_configure(config):
    if not config.option.xmlpath and not hasattr(config, 'slaveinput'):
        xmlpath = "test_report_" + str(int(time.time())) + ".xml"
        config._xml = LogXML(xmlpath, config.option.junitprefix, config.getini('junit_suite_name'))
        config.pluginmanager.register(config._xml)
Другие вопросы по тегам