Pytest html report customization - add new column in report - python

I need help regarding pytest html report customization. I need to print failed network request status code(By TestCase wise) in report so I did the below code. StatusCode column created successfully but not getting data in html report. also, test case-wise statuscode row does not appear in the report.
Conftest.py
#pytest.mark.optionalhook
def pytest_html_results_table_header(cells):
cells.append(html.th('Statuscode'))
#pytest.mark.optionalhook
def pytest_html_result_table_row(report,cells):
cells.append(html.td(report.statuscode))
def pytest_runtest_makereport(item):
"""
Extends the PyTest Plugin to take and embed screenshot in html report, whenever test fails.
:param item:
"""
pytest_html = item.config.pluginmanager.getplugin('html')
outcome = yield
report = outcome.get_result()
setattr(report, "duration_formatter", "%H:%M:%S.%f")
extra = getattr(report, 'extra', [])
statuscode = []
if report.when == 'call' or report.when == "setup":
xfail = hasattr(report, 'wasxfail')
if (report.skipped and xfail) or (report.failed and not xfail):
file_name = report.nodeid.replace("::", "_")+".png"
_capture_screenshot(file_name)
if file_name:
html = '<div><img src="%s" alt="screenshot" style="width:304px;height:228px;" ' \
'onclick="window.open(this.src)" align="right"/></div>' % file_name
extra.append(pytest_html.extras.html(html))
for request in driver.requests:
if url in request.url and request.response.status_code >=400 and request.response.status_code <= 512:
statuscode.append(request.response.status_code)
print("*********Status codes************",statuscode)
report.statuscode=statuscode
report.extra = extra

Related

How to save screenshots including test results, etc. when the test is finished in pytest

I want to save a screenshot when a test fails.
However, the screenshot name must include the information used in the test.
example
-> Currently my code is able to send the city I used in the test.
However, it does not operate according to success or failure.
How can I make the test receive a variable as well and act on success/failure?
(The file name I want: {city}{id}{pass/fail}.png
paris_testaccount01_pass.png)
test_example.py
class TesExample(BaseTest):
def test_example(self, capture_screenshot):
city = "paris"
id = "testaccount01"
# ~~ Skip test content ~~
capture_screenshot(self.driver, city)
BaseTest.py
import pytest
#pytest.mark.usefixtures("get_browser")
class BaseTest:
pass
conftest.py
#pytest.fixture()
def capture_screenshot():
def _capture_screenshot(get_browser, name):
driver = get_browser
driver.get_screenshot_as_file(f'../Screenshots/{name}.png')
return _capture_screenshot
return _capture_screenshot
If you use pytest-html for reporting and If you would take screenshot in case of fail, you can use following code in your conftest:
#mark.hookwrapper
def pytest_runtest_makereport(item, call):
pytest_html = item.config.pluginmanager.getplugin('html')
outcome = yield
report = outcome.get_result()
extra = getattr(report, 'extra', [])
if report.when == 'call':
xfail_state = hasattr(report, 'wasxfail')
if (report.skipped and xfail_state) or (report.failed and not xfail_state):
mydriver = item.funcargs['driver']
screenshot = mydriver.get_screenshot_as_base64()
extra.append(pytest_html.extras.image(screenshot, ''))
report.extra = extra

Screenshot is not getting generated on test failure even if the code for taking screenshot is correct in Selenium Python

I have attached a hook for taking screenshot whenever it encounters a failure and it will attach the screenshot to the report. But, on failure, the screenshot is not getting generated and on clicking the screenshot, the error is coming as 'Your file couldn’t be accessed. It may have been moved, edited, or deleted.
ERR_FILE_NOT_FOUND'
Attaching the hook which was able to capture screenshot successfully. But, now it is not getting generated.
#pytest.mark.hookwrapper
def pytest_runtest_makereport(item):
"""
Extends the PyTest Plugin to take and embed screenshot in html report, whenever test fails.
:param item:
"""
pytest_html = item.config.pluginmanager.getplugin('html')
outcome = yield
report = outcome.get_result()
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):
file_name = report.nodeid.replace("::", "_") + ".png"
_capture_screenshot(file_name)
if file_name:
html = '<div><img src="%s" alt="screenshot" style="width:304px;height:228px;" ' \
'onclick="window.open(this.src)" align="right"/></div>' % file_name
extra.append(pytest_html.extras.html(html))
report.extra = extra
def _capture_screenshot(name):
driver.get_screenshot_as_file(name)
You did not add the path from where to take the screenshots I use something like this:
def remove_files():
download_path = r'E:\iollo\food-generation-ocb-automation-a36cc1ff0a57\scrennshot\**\*.png'
return download_path
Here I add a path to downloaded the screenshots in a folder and than I use the fixture to add the path in the report.
#pytest.hookimpl(hookwrapper=True)
#pytest.mark.hookwrapper
def pytest_runtest_makereport(item, call):
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']
xfail = hasattr(report, "wasxfail")
if (report.skipped and xfail) or (report.failed and not xfail):
feature_request = item.funcargs["request"]
driver = feature_request.getfixturevalue("setup")
timestamp = datetime.now().strftime('%H-%M-%S')
path = "/oalaCuBunatati"
ismount= os.path.ismount(path)
img_name = "name" + timestamp + ".png"
# img_path = os.path.join("D:\GIT\ocb-automation\scrennshot", img_name)
img_path = os.path.join(r'/oalaCuBunatati/scrennshot', img_name)
driver.save_screenshot(img_path)
if (report.skipped and xfail) or (report.failed and not xfail):
# only add additional html on failure
extra.append(pytest_html.extras.image(img_path))
extra.append(pytest_html.extras.html('<div>Additional HTML</div>'))
report.extra = extra
Maybe this will help you, in this way I use to generate the screenshots into html

Error in Adding ScreenShot to Pytest Html Report

I'm unable to add Screen-Shot of failed Scanerios in desired html report.
What I did is just moved creation of html report in other desired folder and i'm getting error that Screen Shot is not getting placed in HTML report
below is my code for ScreenShot present in conftest
#pytest.mark.hookwrapper
def pytest_runtest_makereport(item):
"""
Extends the PyTest Plugin to take and embed screenshot in html report, whenever test fails.
:param item:
"""
pytest_html = item.config.pluginmanager.getplugin('html')
outcome = yield
report = outcome.get_result()
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):
file_name = report.nodeid.replace("::", "_") + ".png"
_capture_screenshot(file_name)
if file_name:
html = '<div><img src="%s" alt="screenshot" style="width:304px;height:228px;" ' \
'onclick="window.open(this.src)" align="right"/></div>' % file_name
extra.append(pytest_html.extras.html(html))
report.extra = extra
def _capture_screenshot(name):
driver.get_screenshot_as_file(name)

Adding a prefix div to Emails HTML body

We're trying to add a warning to every email we find suspicious, but once we do that - not all emails are showing as expected after the change: - on some EMails we ruin the styling and the message is displayed differently, while on others we see the warning at the top of the email (similar to Google warnings).
Are there any best practices for this action of adding a 'prefix' warning on the HTML part of the email? Do's/Don'ts ? Anything would be helpful!
Here's a snippet:
def replace_body(self, email_instance, message_id, **kwargs):
def _generate_html_part_from_plain(_part):
_plain_text_body = _part.get_payload(decode=True)
_content_charset = _part.get_content_charset()
_artificial_html_body = '<div dir="ltr">{}</div>'.format(_plain_text_body.replace('\r\n', '<br>'))
_html_part = MIMEText(_artificial_html_body, 'html', _content_charset)
return _content_charset, _html_part
body_prefix = self.generate_prefix(message_id, email_instance, kwargs)
if not body_prefix:
log('prefix is empty, no need to update body (message={message_id})')
return True
if email_instance.is_multipart():
payload = email_instance.get_payload()
for part in payload:
if part.get_content_subtype() == 'html':
self.log.debug('email is \'multipart\' - attaching HTML part with warning (message={})'
.format(message_id))
prefixed_part = self.attach_email_prefix(body_prefix, part, 'html', part.get_content_charset())
payload.remove(part)
payload.append(prefixed_part)
break
# when no html part present
else:
for part in payload:
if part.get_content_subtype() == 'plain':
self.log.debug('email is \'multipart\', but no \'html\' part found: '
'generating and attaching HTML part with warning (message={})'
.format(message_id))
content_charset, html_part = _generate_html_part_from_plain(part)
prefixed_part = self.attach_email_prefix(body_prefix, html_part, 'html', content_charset)
top_content_subtype = email_instance.get_content_subtype()
if top_content_subtype != 'alternative':
self.log.debug('email\'s top-content-subtype is {}, generating alternative part to hold'
'\'plain\' and \'html\' parts, and attaching to email (message={})'
.format(top_content_subtype, message_id))
alternative_part = MIMEMultipart('alternative')
new_plain_part = MIMEText(part.get_payload(decode=True), 'plain', content_charset)
alternative_part.set_payload([new_plain_part, prefixed_part])
payload.remove(part)
payload.append(alternative_part)
else:
payload.append(prefixed_part)
break
email_instance.set_payload(payload)
elif email_instance.get_content_subtype() == 'plain':
self.log.debug('email is \'text/plain\', attaching artificial HTML part with warning (message={})'
.format(message_id))
# plain_part = deepcopy(email_instance)
content_charset, html_part = _generate_html_part_from_plain(email_instance)
prefixed_part = self.attach_email_prefix(body_prefix, html_part, 'html', content_charset)
email_instance.replace_header('Content-Type', 'multipart/alternative')
new_plain_part = MIMEText(email_instance.get_payload(decode=True), 'plain', content_charset)
email_instance.set_payload([new_plain_part, prefixed_part])
# email_instance.attach(html_part)
else:
self.log.warning('failed to attach HTML warning (message={}, top-content-type={})'
.format(message_id, email_instance.get_content_type()))
log('prefix attached to message successfully (message={message_id})')
return True
def attach_email_prefix(self, prefix, email_instance, subtype='html', charset='us-ascii'):
def attach_to_text(_part):
sep = {'html': '<br>', 'text': '\r\n'}
_part_payload = _part.get_payload(decode=True)
if not isinstance(_part_payload, str):
self.log.debug(
'skipping prefix attaching: Content payload\'s type is not str: {}'.format(_part_payload))
return _part
_part.set_payload('{}{}{}'.format(prefix, sep[subtype], _part_payload), charset)
return _part
if email_instance.get_content_subtype() == subtype:
return attach_to_text(email_instance)

Pytest-html Customization

I am using pytest-html plugin for report generation for my test cases. I want to add a line item if the script fails. So here's my code---
import pytest
#pytest.mark.hookwrapper
def pytest_runtest_makereport(item, call):
pytest_html = item.config.pluginmanager.getplugin('html')
outcome = yield
report = outcome.get_result()
extra = getattr(report, 'extra', [])
if report.when == 'call':
# 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.html('<div>Additional HTML</div>'))
report.extra = extra
def test_sayHello():
assert False, "I mean for this to fail"
print "hello"
def test_sayBye():
print "Bye"
I am running the scipt using -
pytest --html=report.html
I can see the report getting generatesd but it doesnt have a line item as Additional HTML.
Also is there a way via which I can add such line items in between of my scripts to the report.
Really appreciate help.
This should work:
#pytest.mark.hookwrapper
def pytest_runtest_makereport(item, call):
pytest_html = item.config.pluginmanager.getplugin('html')
outcome = yield
report = outcome.get_result()
extra = getattr(report, 'extra', [])
if report.when == 'call':
extra.append(pytest_html.extras.html('<p>some html</p>'))
report.extra = extra

Categories

Resources