Как установить динамические параметры по умолчанию для 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)