Reputation: 99
I have a framework which working under py.test. py.test can generate beauty reports with params --html and --junitxml. But clients that using my framework not always type this params to command line where they using py.test. I want make py.test to generate reports always when the py.test used with my framework. And i want to put this reports with log folder. So i need to generate path for report in runtime. Can i do this by fixtures? Or maybe by the plugin API?
Upvotes: 7
Views: 5010
Reputation: 66501
The part of my answer with the custom plugin is way too overengineered; it is already sufficient to just reassign the xmlpath
option as in this answer. Use that instead. The XML plugin reconfiguration is only needed if you want to make deeper changes in XML report assembly, which isn’t the case here.
First of all, if you want to implicitly add the command line args to pytest
, you can use the pytest.ini
placed in the tests root dir with the addopts
config value:
[pytest]
addopts=--verbose --junit-xml=/tmp/myreport.xml # etc
Of course, if you want to dynamically calculate the directory to store the reports, then you can't put it in the config and will need to extend pytest
. The best spot would be the pytest_configure
hook. Example:
# 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 you remove the first if
block, then pytest
will completely ignore --junit-xml
arg passed via command line or in addopts
value in config.
Example run:
$ 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/stackoverflow/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 ==================================
The xml report is now put in a tempfile.
Upvotes: 6
Reputation: 9475
Just to keep things more clear, pytest uses argparse
and the request.config.option
is a argparse.Namespace
object. Then, if you would like to simulate a command line option as pytest ... --docker-compose-remove-volumes
, you can directly attribute the option docker_compose_remove_volumes
to request.config.option
(because --docker-compose-remove-volumes
is converted to docker_compose_remove_volumes
by argparse module).
This examples inverts the default option for --docker-compose-remove-volumes
which is false. But allow you to enable it back by providing --keep-containers
option to 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
Upvotes: 0
Reputation: 1135
Putting this in conftest.py will suffice:
def pytest_configure(config):
if config.option.xmlpath is None:
config.option.xmlpath = get_custom_xml_path() # implement this
The accepted answer is probably a bit more complicated than necessary for most people for a few reasons:
Upvotes: 7
Reputation: 127
@hoefling's answer worked perfectly for me in conftest.py. the code looks simpler there.
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)
Upvotes: 0
Reputation: 200
Configure pytest.ini file with parameters:
# content of pytest.ini
[pytest]
addopts = --html=report.html --self-contained-html
;addopts = -vv -rw --html=./results/report.html --self-contained-html
Upvotes: 0