1
votes

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
2
what do you mean by you need all the screenshots? what's happening right now? isn't it able to embed the screenshot?Gaurang Shah
Right now I am getting screenshots only when a test fails. I want a code or snippet or plugin which will add a screenshot to html report irrespective of test passes or fails.Sanket Lad
If you want to create a robotframework-like report, you just need to generate an xml file in the format that robot uses (which is a very simple structure), and then call rebot on it.Bryan Oakley
two things. I don't see a code where you are attaching your screenshot to html report and I don't see a code where you check if test has failed. so just add the code to attach the screenshot and everything will be okayGaurang Shah
We do not need to write a code where test fails. It attaches screenshot by default. Lets say in above method if I wrote "assert False" after opening a browser, then it will fail with screenshot. I want following line to be included in report driver.save_screenshot('googlehome.png')Sanket Lad

2 Answers

1
votes

You have to pass webdriver from test into pytest reporting system. In my case I use webdriver as fixtuer. 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))
0
votes

Here is how I solved mine:

Okay so here is how you access webdriver from the report generation hook:

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

timestamp = datetime.now().strftime('%H-%M-%S')

pytest_html = item.config.pluginmanager.getplugin('html')
outcome = yield
report = outcome.get_result()
extra = getattr(report, 'extra', [])
if report.when == 'call':

    feature_request = item.funcargs['request']

    driver = feature_request.getfuncargvalue('browser')
    driver.save_screenshot('D:/report/scr'+timestamp+'.png')

    extra.append(pytest_html.extras.image('D:/report/scr'+timestamp+'.png'))

    # always add url to report
    extra.append(pytest_html.extras.url('http://www.example.com/'))
    xfail = hasattr(report, 'wasxfail')
    if (report.skipped and xfail) or (report.failed and not xfail):
        # only add additional html on failure
        extra.append(pytest_html.extras.image('D:/report/scr.png'))
        extra.append(pytest_html.extras.html('<div>Additional HTML</div>'))
    report.extra = extra