From 47fbe0f2f994b3f3064a3a36f040255ccb1ab092 Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Tue, 14 Apr 2015 22:46:30 +0300 Subject: [PATCH] Error messages in BDD are always converted to UTF-8 regardless python version for PY-15258 --- python/helpers/pycharm/_bdd_utils.py | 48 ++++++++++++++++++++++-- python/helpers/pycharm/behave_runner.py | 10 +++-- python/helpers/pycharm/lettuce_runner.py | 2 +- 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/python/helpers/pycharm/_bdd_utils.py b/python/helpers/pycharm/_bdd_utils.py index a71cc37e346d..4d4116197ff4 100644 --- a/python/helpers/pycharm/_bdd_utils.py +++ b/python/helpers/pycharm/_bdd_utils.py @@ -8,7 +8,7 @@ You may also need "get_what_to_run_by_env" that gets folder (current or passed a import os import time import abc - +import sys import tcmessages @@ -139,11 +139,11 @@ class BddRunner(object): :param name: test name :type name str :param message: failure message - :type message str + :type message basestring :param details: failure details (probably stacktrace) :type details str """ - self.tc_messages.testFailed(name, message=message, details=details) + self.tc_messages.testFailed(name, message=VersionAgnosticUtils().to_unicode(message), details=details) self.__last_test_name = None def _test_passed(self, name, duration=None): @@ -229,3 +229,45 @@ class BddRunner(object): pass +class VersionAgnosticUtils(object): + """ + "six" emulator: this class fabrics appropriate tool to use regardless python version. + Use it to write code that works both on py2 and py3 + """ + + @staticmethod + def __new__(cls, *more): + """ + Fabrics Py2 or Py3 instance based on py version + """ + real_class = _Py3KUtils if sys.version_info >= (3, 0) else _Py2Utils + return super(cls, real_class).__new__(real_class, *more) + + def to_unicode(self, obj): + """ + + :param obj: string to convert to unicode + :return: unicode string + """ + + raise NotImplementedError() + + + +class _Py2Utils(VersionAgnosticUtils): + """ + Util for Py2 + """ + def to_unicode(self, obj): + if isinstance(obj, unicode): + return obj + return unicode(obj.decode("utf-8")) + + + +class _Py3KUtils(VersionAgnosticUtils): + """ + Util for Py3 + """ + def to_unicode(self, obj): + return str(obj) \ No newline at end of file diff --git a/python/helpers/pycharm/behave_runner.py b/python/helpers/pycharm/behave_runner.py index f35c7e242021..7072e47e615b 100644 --- a/python/helpers/pycharm/behave_runner.py +++ b/python/helpers/pycharm/behave_runner.py @@ -136,9 +136,10 @@ class _BehaveRunner(_bdd_utils.BddRunner): :param element feature/suite/step """ element.location.file = element.location.filename # To preserve _bdd_utils contract + utils = _bdd_utils.VersionAgnosticUtils() if isinstance(element, Step): # Process step - step_name = "{0} {1}".format(element.keyword, element.name) + step_name = u"{0} {1}".format(utils.to_unicode(element.keyword), utils.to_unicode(element.name)) if is_started: self._test_started(step_name, element.location) elif element.status == 'passed': @@ -148,9 +149,10 @@ class _BehaveRunner(_bdd_utils.BddRunner): trace = traceback.format_exc() except Exception: trace = "".join(traceback.format_tb(element.exc_traceback)) - if trace in str(element.error_message): - trace = None # No reason to duplicate output (see PY-13647) - self._test_failed(step_name, element.error_message, trace) + error_message = utils.to_unicode(element.error_message) + if "Traceback " in error_message: + error_message = "" # No reason to duplicate output (see PY-13647) + self._test_failed(step_name, error_message, trace) elif element.status == 'undefined': self._test_undefined(step_name, element.location) else: diff --git a/python/helpers/pycharm/lettuce_runner.py b/python/helpers/pycharm/lettuce_runner.py index b61f7af9a332..2c97672b69cb 100644 --- a/python/helpers/pycharm/lettuce_runner.py +++ b/python/helpers/pycharm/lettuce_runner.py @@ -103,7 +103,7 @@ class _LettuceRunner(_bdd_utils.BddRunner): elif step.failed: reason = step.why assert isinstance(reason, ReasonToFail), reason - self._test_failed(test_name, message=reason.exception, details=reason.traceback) + self._test_failed(test_name, message=reason.exception.message, details=reason.traceback) elif step.has_definition: self._test_skipped(test_name, "In lettuce, we do know the reason", step.described_at) else: