philomath
philomath

Reputation: 133

pytest's html reporter doesn't take/show screenshot in the test reports for pytest-playwright based tests

I tried to run my first playwright test using pytest-playwright and the test runs fine but when I tried to use the pytest html reporter to show me the report with a screenshot for a failed test it doesn't work

pytest version == 7.0.1 pytest-playwright version == 0.2.3

Test which is expected to fail:

    def test_pw():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)
        page = browser.new_page()
        page.goto("http://www.html")
        browser.close()

test report without any screenshot for failed test

Run command: pytest --html report_pw1.html

Can anyone please suggest what am i missing here? I read the docs for pytest html and it says that a screenshot should automatically be included by default for failed tests but its not happening so

Upvotes: 2

Views: 3966

Answers (3)

Vivek Kumar
Vivek Kumar

Reputation: 59

I had a hard time using the same code which is present in documentation of pytest-html. I was not able to see the image in test report when test case is failed. It was showing and icon of image not loaded.

Bad Image

Then I had to alter the documentation code a little. I found that screenshot file present in screenshot folder but not attached to the report. Exact reson was it was not able to find the absolute path of the PNG file.

You have to add a PNG file starting from root i:e C:.....\report\screenshots\test.png as shown below

Report With Image Absolute Path

Now see the code i have altered:

#conftest.py
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
    pytest_html = item.config.pluginmanager.getplugin("html")
    outcome = yield
    screen_file = ""
    report = outcome.get_result()
    extra = getattr(report, "extra", [])
    working_root = pathlib.Path().resolve() #This line here
    if report.when == "call":
        if report.failed and "page" in item.funcargs:
            page = item.funcargs["page"]
            screenshot_dir = Path(working_root , "report/screenshots") #This line here
            screenshot_dir.mkdir(exist_ok=True)
            screen_file = str(f"{slugify(item.nodeid)}.png")
            img_path = os.path.join(screenshot_dir, screen_file) #This line here
            page.screenshot(path=img_path)
        xfail = hasattr(report, "wasxfail")
        if (report.skipped and xfail) or (report.failed and not xfail):
            # add the screenshots to the html report
            extra.append(pytest_html.extras.image(img_path))
        report.extra = extra

Upvotes: 0

Jlearner
Jlearner

Reputation: 613

If you meant plugin pytest-html-reporter (not pytest-html) then below implementation for capturing screenshot might help

Note: driver initialisation needs to be done in a method name setup in conftest.py using a pytest fixture

from pytest_html_reporter import attach
import pytest

@pytest.mark.usefixtures("setup")
class BaseClass:
    pass

class TestClass(BaseClass):

    def test_pass(self):
        assert True

    def test_fail(self):
        assert False


    def teardown_method(self):
        '''to capture screenshot on test method failure'''
        attach(data=self.driver.get_screenshot_as_png())

Upvotes: 0

Leonardo Martinez
Leonardo Martinez

Reputation: 633

You have to create conftest.py file at the root level. I adapted this code from pytest-html official documentation:

# conftest.py
import pytest

@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
    pytest_html = item.config.pluginmanager.getplugin("html")
    outcome = yield
    screen_file = ''
    report = outcome.get_result()
    extra = getattr(report, "extra", [])
    if report.when == "call":
        if report.failed and "page" in item.funcargs:
            page = item.funcargs["page"]
            screenshot_dir = Path("screenshots")
            screenshot_dir.mkdir(exist_ok=True)
            screen_file = str(screenshot_dir / f"{slugify(item.nodeid)}.png")
            page.screenshot(path=screen_file)
        xfail = hasattr(report, "wasxfail")
        if (report.skipped and xfail) or (report.failed and not xfail):
            # add the screenshots to the html report
            extra.append(pytest_html.extras.png(screen_file))
        report.extra = extra

You have to install pytest-playwright:

pip install pytest-playwright

Then your tests have access to the page fixture (and it is available for item.funcargs in the conftest.py file):

def test_example_is_failing(page):
    page.goto("https://example.com")
    assert page.inner_text('h1') == 'Any text to make it fail'

I am sure there should be a better way if we dig more in the documentation. I used these links:

Upvotes: 3

Related Questions