Question: I have a problem with setting report name and folder with it dynamically in Python's pytest. For example: I've run all pytest's tests @ 2020-03-06 21:50 so I'd like to have my report stored in folder 20200306 with name report_2150.html. I want it to be automated and triggered right after the tests are finished. I'm working in VS Code and I'm aiming to share my work with colleagues with no automation experience so I'm aiming to use it as "click test to start". My project structure: webtools/ |── .vscode/ |──── settings.json |── drivers/ |── pages/ |── reports/ |── tests/ |──── __init__.py |──── config.json |──── conftest.py |──── test_1.py |──── test_2.py |── setup.py  Code samples: settings.json { "python.linting.pylintEnabled": false, "python.linting.flake8Enabled": true, "python.linting.enabled": true, "python.pythonPath": "C:\\Users\\user\\envs\\webtools\\Scripts\\python.exe", "python.testing.pytestArgs": [ "tests", "--self-contained-html", "--html=./reports/tmp_report.html" ], "python.testing.unittestEnabled": false, "python.testing.nosetestsEnabled": false, "python.testing.pytestEnabled": true, "python.testing.unittestArgs": [ "-v", "-s", "./tests", "-p", "test_*.py" ] }  config.json { "browser": "chrome", "wait_time": 10 }  conftest.py import json import pytest from datetime import datetime import time import shutil import os from selenium import webdriver from selenium.webdriver import Chrome CONFIG_PATH = 'tests/config.json' DEFAULT_WAIT_TIME = 10 SUPPORTED_BROWSERS = ['chrome', 'explorer'] @pytest.fixture(scope='session') def config(): # Read the JSON config file and returns it as a parsed dict with open(CONFIG_PATH) as config_file: data = json.load(config_file) return data @pytest.fixture(scope='session') def config_browser(config): # Validate and return the browser choice from the config data if 'browser' not in config: raise Exception('The config file does not contain "browser"') elif config['browser'] not in SUPPORTED_BROWSERS: raise Exception(f'"{config["browser"]}" is not a supported browser') return config['browser'] @pytest.fixture(scope='session') def config_wait_time(config): # Validate and return the wait time from the config data return config['wait_time'] if 'wait_time' in config else DEFAULT_WAIT_TIME @pytest.fixture def browser(config_browser, config_wait_time): # Initialize WebDriver if config_browser == 'chrome': driver = webdriver.Chrome(r"./drivers/chromedriver.exe") elif config_browser == 'explorer': driver = webdriver.Ie(r"./drivers/IEDriverServer.exe") else: raise Exception(f'"{config_browser}" is not a supported browser') # Wait implicitly for elements to be ready before attempting interactions driver.implicitly_wait(config_wait_time) # Maximize window for test driver.maximize_window() # Return the driver object at the end of setup yield driver # For cleanup, quit the driver driver.quit() @pytest.fixture(scope='session') def cleanup_report(): timestamp = datetime.now().strftime('%Y%m%d_%H%M%S') os.chdir("./reports") os.mkdir(timestamp) yield shutil.move("./tmp_report.html", "./%s/test_report.html" % timestamp)  In current situation the report is created as tmp_report.html in the reports folder, but I don't know how I can force running cleanup_report() after all tests are completed and tmp_report.html is present and complete in folder. For checking if complete I assume I'd have to verify if all html tags have their closing (or at least <html> one). Can somebody help me with that? If you need some further code portions I'll provide them as soon as possible. Thank you in advance!

Answer: You can customize the plugin options in a custom impl of the pytest_configure hook. Put this example code in a conftest.py file in your project root dir: from datetime import datetime from pathlib import Path import pytest @pytest.hookimpl(tryfirst=True) def pytest_configure(config): # set custom options only if none are provided from command line if not config.option.htmlpath: now = datetime.now() # create report target dir reports_dir = Path('reports', now.strftime('%Y%m%d')) reports_dir.mkdir(parents=True, exist_ok=True) # custom report file report = reports_dir / f"report_{now.strftime('%H%M')}.html" # adjust plugin options config.option.htmlpath = report config.option.self_contained_html = True  If you want to completely ignore what's passed from command line, remove the if not config.option.htmlpath: condition. If you want to stick with your current impl, notice that on fixtures teardown, pytest-html hasn't written the report yet. Move the code from cleanup_report to a custom impl of the pytest_sessionfinish hook to ensure pytest-html has already written the default report file: @pytest.hookimpl(trylast=True) def pytest_sessionfinish(session, exitstatus): shutil.move(...)