pytest-dev / pytest-html

Plugin for generating HTML reports for pytest results
Other
707 stars 236 forks source link

How to add screenshot to report when result is ERROR #838

Open vladimir-popescu-idnow opened 4 weeks ago

vladimir-popescu-idnow commented 4 weeks ago

Hello,

I have an automation framework with selenium/pytest with some fixtures in the test modules which execute repetitive code. In case the execution fails in the fixture this is marked as ERROR in the html report and despite being able to take a screenshot on this occurrence it is not attached to the report. A few more details :

Example test & fixture

@pytest.fixture(autouse=True)
def open_userdata_page(vi_rewrite_gui):
    """
    Autouse fixture which opens userdata page before each test
    """
    vi_rewrite_gui.open_userdata_page(shortname)

def test_validation_errors(vi_rewrite_gui):
    """
    Check validation errors when trying to proceed without filling any info
    """
    vi_rewrite_gui.click_continue_btn()
    actual_validation_errors = vi_rewrite_gui.get_validation_errors()
    assert expected_validation_errors == actual_validation_errors

Conftest hook

@pytest.mark.hookwrapper
def pytest_runtest_makereport(item):

    pytest_html = item.config.pluginmanager.getplugin('html')
    outcome = yield
    report = outcome.get_result()
    report.description = str(item.function.__doc__)
    extra = getattr(report, 'extra', [])
    if report.when == 'call' or report.when == "setup":
        xfail = hasattr(report, 'wasxfail')
        if (report.skipped and xfail) or (report.failed and not xfail):
            driver = DRIVER_REGISTRY.get(item.nodeid)
            if driver:
                # driver = item.funcargs['driver_mod']
                timestamp = datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
                screenshot_name = f"{item.name}_{timestamp}.png"
                driver.save_screenshot(os.path.join(SCREENSHOTS_PATH, screenshot_name))
                build_img_path_and_div_for_html(screenshot_name, extra, pytest_html)
        report.extra = extra

report

vladimir-popescu-idnow commented 3 weeks ago

The function build_img_path_and_div_for_html does the extra.append

def build_img_path_and_div_for_html(filename, extra, pytest_html):
    rel_path = "screenshots/" + filename
    extra.append(pytest_html.extras.html(
        f'<div class="image"><img src="{rel_path}"/></div>')
    )

I've also tried the following way with the same result

driver = DRIVER_REGISTRY.get(item.nodeid, {}).get("driver_mod")
            if driver:
                # driver = item.funcargs['driver_mod']
                timestamp = datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
                screenshot_name = f"{item.name}_{timestamp}.png"
                driver.save_screenshot(os.path.join(SCREENSHOTS_PATH, screenshot_name))
                # build_img_path_and_div_for_html(screenshot_name, extra, pytest_html)
                rel_path = "screenshots/" + screenshot_name
                extra.append(pytest_html.extras.image(rel_path))