diff --git a/fixtures/artifactor_plugin.py b/fixtures/artifactor_plugin.py index 25dc746a9e..96da10a4f9 100644 --- a/fixtures/artifactor_plugin.py +++ b/fixtures/artifactor_plugin.py @@ -33,6 +33,7 @@ from utils.conf import env, credentials from utils.net import random_port, net_check from utils.wait import wait_for +from utils.pytest_shortcuts import report_safe_longrepr from utils import version UNDER_TEST = False # set to true for artifactor using tests @@ -219,10 +220,7 @@ def pytest_runtest_logreport(report): if hasattr(report, 'skipped'): if report.skipped: - try: - contents = report.longrepr[2] - except AttributeError: - contents = str(report.longrepr) + contents = report_safe_longrepr(report) fire_art_hook( config, 'filedump', test_location=location, test_name=name, diff --git a/fixtures/browser.py b/fixtures/browser.py index e870f3f9c8..e17dd452b6 100644 --- a/fixtures/browser.py +++ b/fixtures/browser.py @@ -33,7 +33,7 @@ def pytest_exception_interact(node, call, report): from httplib import BadStatusLine from socket import error from utils.browser import WharfFactory - + from utils.pytest_shortcuts import report_safe_longrepr import urllib2 val = safe_string(call.excinfo.value.message).decode('utf-8', 'ignore') @@ -48,9 +48,10 @@ def pytest_exception_interact(node, call, report): short_tb = '{}\n{}'.format( call.excinfo.type.__name__, val.encode('ascii', 'xmlcharrefreplace')) + longrepr = report_safe_longrepr(report) fire_art_test_hook( node, 'filedump', - description="Traceback", contents=str(report.longrepr), file_type="traceback", + description="Traceback", contents=longrepr, file_type="traceback", display_type="danger", display_glyph="align-justify", group_id="pytest-exception", slaveid=store.slaveid) fire_art_test_hook( @@ -60,7 +61,7 @@ def pytest_exception_interact(node, call, report): slaveid=store.slaveid) # base64 encoded to go into a data uri, same for screenshots - full_tb = str(report.longrepr).encode('base64').strip() + full_tb = longrepr.encode('base64').strip() # errors are when exceptions are thrown outside of the test call phase report.when = getattr(report, 'when', 'setup') is_error = report.when != 'call' diff --git a/fixtures/log.py b/fixtures/log.py index 54ae1b7431..b8b8451eaf 100644 --- a/fixtures/log.py +++ b/fixtures/log.py @@ -3,7 +3,7 @@ import pytest from utils import log - +from utils.pytest_shortcuts import report_safe_longrepr #: A dict of tests, and their state at various test phases test_tracking = collections.defaultdict(dict) @@ -57,13 +57,7 @@ def pytest_runtest_logreport(report): test_status)), extra={'source_file': path, 'source_lineno': lineno}) if report.outcome == "skipped": - # Usualy longrepr's a tuple, other times it isn't... :( - try: - longrepr = report.longrepr[-1] - except AttributeError: - longrepr = str(report.longrepr) - - logger().info(log.format_marker(longrepr)) + logger().info(log.format_marker(report_safe_longrepr(report))) def pytest_exception_interact(node, call, report): diff --git a/utils/pytest_shortcuts.py b/utils/pytest_shortcuts.py index 04e71bc0c6..aae014b916 100644 --- a/utils/pytest_shortcuts.py +++ b/utils/pytest_shortcuts.py @@ -16,3 +16,21 @@ def extract_fixtures_values(item): # This can cause some problems if the fixtures are used in the guards in this case, but # that will tell use where is the problem and we can then find it out properly. return {} + + +def report_safe_longrepr(report): + """savely extract the longrepr text of a test report + + Args: + report: a test report + Returns: + :py:class:`str` with the long repr text extracted + """ + # Usualy longrepr's a tuple, other times it isn't... :( + try: + longrepr = report.longrepr[-1] + except (AttributeError, TypeError): + # type error for python 3 and pytest > 3 + # Attributeerror for old style classes on python2 + longrepr = str(report.longrepr) + return longrepr