Search code examples
pythonseleniumpytestgherkinpytest-html

How to include selenium screenshot in pytest bdd for passed tests?


I am writing tests in pytest bdd with selenium. I am using pytest-html to generate report. For debug purpose or just to have a proper logging, I want selenium screenshots and rest of the logs in html report. But I am unable to have selenium screenshot in passed report.

Here are the things I am trying. There is a pytest-html hook wrapper in conftest.py

conftest.py

@pytest.mark.hookwrapper
def pytest_runtest_makereport(item, call):
    pytest_html = item.config.pluginmanager.getplugin('html')
    outcome = yield
    report = outcome.get_result()
    print("printing report")
    extra = getattr(report, 'extra', [])
    if report.when == 'call':
        mylogs = ""
        with open('/tmp/test.log', 'r') as logfile:
            for line in logfile:
                mylogs = mylogs + line + "<br>"
        extra.append(pytest_html.extras.html('<html><body>{}</body></html>'.format(mylogs)))
        report.extra = extra

This code is adding logs in my report.html Similarly, I will be adding few selenium screenshots in my test code. I want to know if we can generate a report containing all selenium screenshots.

Following is my test file

test_file.py

def test_case():
    logger.info("I will now open browser")
    driver = webdriver.Chrome()
    driver.get('http://www.google.com')
    driver.save_screenshot('googlehome.png')
    time.sleep(3)
    driver.quit()

I want googlehome.png and all other png file to be part of html report. I will be great if the we can generate a robot framework like html report.

Is there any way in pytest we can do that?

Following is the command I use to generate report

py.test -s --html=report.html --self-contained-html  -v

Solution

  • You have to pass webdriver from test into pytest reporting system. In my case I use webdriver as fixture. That have a lot of other advantages - for example you can test for any set of browsers and control that from one place.

    @pytest.fixture(scope='session', params=['chrome'], ids=lambda x: 'Browser: {}'.format(x))
    def web_driver(request):
        browsers = {'chrome': webdriver.Chrome}
        return browsers[]()
    
    
    def test_case(web_driver):
        logger.info("I will now open browser")
        web_driver.get('http://www.google.com')
    
    
    @pytest.hookimpl(tryfirst=True, hookwrapper=True)
    def pytest_runtest_makereport(item, call):
        outcome = yield
        rep = outcome.get_result()
        if rep.when == 'call' and not rep.failed:
            try:
                if 'web_driver' in item.fixturenames:
                    web_driver = item.funcargs['web_driver']
                else:
                    return  # This test does not use web_driver and we do need screenshot for it
            # web_driver.save_screenshot and other magic to add screenshot to your report
        except Exception as e:
            print('Exception while screen-shot creation: {}'.format(e))