I am using pytest with pytest-html module to generate an HTML test report.
In the tear-down stage I automatically open the generated HTML report in the browser with webbrowser.open('file:///path_to_report.html')
— this works fine, but I am running the test with different arguments and for each set of arguments I am setting a different report file via command line arguments:
pytest -v mytest.py::TestClassName --html=report_localhost.html
My tear-down code looks like this:
@pytest.fixture(scope='class')
def config(request):
claz = request.cls
claz.host = request.config.getoption("--host", default=HOST_DEFAULT)
...
def teardown_env():
print('destroying test harness')
webbrowser.open("file:///path_to_report_localhost.html")
request.addfinalizer(teardown_env)
return "prepare_env"
The question is how to access the report file name from the tear-down hook in the test so that instead of hard-coding it I can use whatever path was passed in as command line argument, i.e. --html=report_for_host_xyz.html
?
Using a class-scoped fixture for displaying the generated HTML is not the correct approach because pytest-html
hooks the report generation into the session finalizer scope which means that by the time the class finalizer is called the report is still not generated and you might need to refresh the browser page to actually see the report. And if it seems to work it's only because the browser window might take some extra seconds to open which might allow the report generation to finish by the time the file is loaded in the browser.
The correct way to do it is explained in this answer and boils down to using the pytest_unconfigure
hook.
You can put a breakpoint in the fixture, and look into request.config.option
object — this is where pytest puts all the argparsed's keys.
The one that you look for is request.config.option.htmlpath
.
@pytest.fixture(scope='class')
def config(request):
claz = request.cls
claz.host = request.config.getoption("--host", default=HOST_DEFAULT)
yield 100 # a value of the fixture for the tests
print('destroying test harness')
webbrowser.open("file:///{}".format(request.config.option.htmlpath))
Or you can do the same as for the --host
key:
@pytest.fixture(scope='class')
def config(request):
claz = request.cls
claz.host = request.config.getoption("--host", default=HOST_DEFAULT)
yield 100 # a value of the fixture for the tests
print('destroying test harness')
webbrowser.open("file:///{}".format(request.config.getoption("--html")))