From 7ed6a4371e2f105aa9e7389c244ed98f7a853564 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Wed, 20 Jun 2012 12:27:32 +0400 Subject: [PATCH] fixed PY-6743 Not able to see the difference for failed tests in py3 - link is not available --- python/helpers/pycharm/tcunittest.py | 254 ++++++++++++++------------- 1 file changed, 134 insertions(+), 120 deletions(-) diff --git a/python/helpers/pycharm/tcunittest.py b/python/helpers/pycharm/tcunittest.py index 1de61bf05a0e..1311fa350a20 100644 --- a/python/helpers/pycharm/tcunittest.py +++ b/python/helpers/pycharm/tcunittest.py @@ -7,166 +7,180 @@ from tcmessages import TeamcityServiceMessages PYTHON_VERSION_MAJOR = sys.version_info[0] def strclass(cls): - if not cls.__name__: - return cls.__module__ - return "%s.%s" % (cls.__module__, cls.__name__) + if not cls.__name__: + return cls.__module__ + return "%s.%s" % (cls.__module__, cls.__name__) def smart_str(s): - encoding='utf-8' - errors='strict' - if PYTHON_VERSION_MAJOR < 3: - is_string = isinstance(s, basestring) - else: - is_string = isinstance(s, str) - if not is_string: - try: - return str(s) - except UnicodeEncodeError: - if isinstance(s, Exception): - # An Exception subclass containing non-ASCII data that doesn't - # know how to print itself properly. We shouldn't raise a - # further exception. - return ' '.join([smart_str(arg) for arg in s]) - return unicode(s).encode(encoding, errors) - elif isinstance(s, unicode): - return s.encode(encoding, errors) - else: - return s + encoding='utf-8' + errors='strict' + if PYTHON_VERSION_MAJOR < 3: + is_string = isinstance(s, basestring) + else: + is_string = isinstance(s, str) + if not is_string: + try: + return str(s) + except UnicodeEncodeError: + if isinstance(s, Exception): + # An Exception subclass containing non-ASCII data that doesn't + # know how to print itself properly. We shouldn't raise a + # further exception. + return ' '.join([smart_str(arg) for arg in s]) + return unicode(s).encode(encoding, errors) + elif isinstance(s, unicode): + return s.encode(encoding, errors) + else: + return s class TeamcityTestResult(TestResult): - def __init__(self, stream=sys.stdout): - TestResult.__init__(self) + def __init__(self, stream=sys.stdout): + TestResult.__init__(self) - self.output = stream - self.messages = TeamcityServiceMessages(self.output, prepend_linebreak=True) - self.messages.testMatrixEntered() - self.current_suite = None + self.output = stream + self.messages = TeamcityServiceMessages(self.output, prepend_linebreak=True) + self.messages.testMatrixEntered() + self.current_suite = None - def find_first(self, val): - quot = val[0] + def find_first(self, val): + quot = val[0] + count = 1 + quote_ind = val[count:].find(quot) + while val[count+quote_ind-1] == "\\": + count = count + quote_ind + 1 + quote_ind = val[count:].find(quot) + + return val[0:quote_ind+count+1] + + def find_second(self, val): + val_index = val.find("!=") + if val_index != -1: count = 1 + val = val[val_index+2:].strip() + quot = val[0] quote_ind = val[count:].find(quot) while val[count+quote_ind-1] == "\\": count = count + quote_ind + 1 quote_ind = val[count:].find(quot) - return val[0:quote_ind+count+1] - def find_second(self, val): + else: quot = val[-1] count = 0 quote_ind = val[:len(val)-count-1].rfind(quot) while val[quote_ind-1] == "\\": quote_ind = val[:quote_ind-1].rfind(quot) - return val[quote_ind:] - def formatErr(self, err): - exctype, value, tb = err - return ''.join(traceback.format_exception(exctype, value, tb)) + def formatErr(self, err): + exctype, value, tb = err + return ''.join(traceback.format_exception(exctype, value, tb)) - def getTestName(self, test): - if hasattr(test, '_testMethodName'): - if test._testMethodName == "runTest": - return str(test) - return test._testMethodName - else: - return str(test) + def getTestName(self, test): + if hasattr(test, '_testMethodName'): + if test._testMethodName == "runTest": + return str(test) + return test._testMethodName + else: + return str(test) - def getTestId(self, test): - return test.id + def getTestId(self, test): + return test.id - def addSuccess(self, test): - TestResult.addSuccess(self, test) + def addSuccess(self, test): + TestResult.addSuccess(self, test) - def addError(self, test, err): - TestResult.addError(self, test, err) + def addError(self, test, err): + TestResult.addError(self, test, err) - err = self.formatErr(err) + err = self.formatErr(err) - self.messages.testError(self.getTestName(test), - message='Error', details=err) + self.messages.testError(self.getTestName(test), + message='Error', details=err) - def find_error_value(self, err): - error_value = traceback.extract_tb(err) - error_value = error_value[-1][-1] - return error_value.split('assert')[-1].strip() + def find_error_value(self, err): + error_value = traceback.extract_tb(err) + error_value = error_value[-1][-1] + return error_value.split('assert')[-1].strip() - def addFailure(self, test, err): - TestResult.addFailure(self, test, err) + def addFailure(self, test, err): + TestResult.addFailure(self, test, err) - error_value = smart_str(err[1]) - if not len(error_value): - # means it's test function and we have to extract value from traceback - error_value = self.find_error_value(err[2]) + error_value = smart_str(err[1]) + if not len(error_value): + # means it's test function and we have to extract value from traceback + error_value = self.find_error_value(err[2]) - if (error_value.startswith("'") or error_value.startswith('"')) and \ - (error_value.endswith("'") or error_value.endswith('"')): - # let's unescape strings to show sexy multiline diff in PyCharm. - # By default all caret return chars are escaped by testing framework - first = self._unescape(self.find_first(error_value)) - second = self._unescape(self.find_second(error_value)) - else: - first = second = "" - err = self.formatErr(err) + self_find_first = self.find_first(error_value) + self_find_second = self.find_second(error_value) + quotes = ["'", '"'] + if (self_find_first[0] == self_find_first[-1] and self_find_first[0] in quotes and + self_find_second[0] == self_find_second[-1] and self_find_second[0] in quotes): + # let's unescape strings to show sexy multiline diff in PyCharm. + # By default all caret return chars are escaped by testing framework + first = self._unescape(self_find_first) + second = self._unescape(self_find_second) + else: + first = second = "" + err = self.formatErr(err) - self.messages.testFailed(self.getTestName(test), - message='Failure', details=err, expected=first, actual=second) + self.messages.testFailed(self.getTestName(test), + message='Failure', details=err, expected=first, actual=second) - def addSkip(self, test, reason): - self.messages.testIgnored(self.getTestName(test), message=reason) + def addSkip(self, test, reason): + self.messages.testIgnored(self.getTestName(test), message=reason) - def __getSuite(self, test): - if hasattr(test, "suite"): - suite = strclass(test.suite) - suite_location = test.suite.location - location = test.suite.abs_location - if hasattr(test, "lineno"): - location = location + ":" + str(test.lineno) - else: - location = location + ":" + str(test.test.lineno) + def __getSuite(self, test): + if hasattr(test, "suite"): + suite = strclass(test.suite) + suite_location = test.suite.location + location = test.suite.abs_location + if hasattr(test, "lineno"): + location = location + ":" + str(test.lineno) else: - suite = strclass(test.__class__) - suite_location = "python_uttestid://" + suite - location = "python_uttestid://" + str(test.id()) + location = location + ":" + str(test.test.lineno) + else: + suite = strclass(test.__class__) + suite_location = "python_uttestid://" + suite + location = "python_uttestid://" + str(test.id()) - return (suite, location, suite_location) + return (suite, location, suite_location) - def startTest(self, test): - suite, location, suite_location = self.__getSuite(test) - if suite != self.current_suite: - if self.current_suite: - self.messages.testSuiteFinished(self.current_suite) - self.current_suite = suite - self.messages.testSuiteStarted(self.current_suite, location=suite_location) - setattr(test, "startTime", datetime.datetime.now()) - self.messages.testStarted(self.getTestName(test), location=location) + def startTest(self, test): + suite, location, suite_location = self.__getSuite(test) + if suite != self.current_suite: + if self.current_suite: + self.messages.testSuiteFinished(self.current_suite) + self.current_suite = suite + self.messages.testSuiteStarted(self.current_suite, location=suite_location) + setattr(test, "startTime", datetime.datetime.now()) + self.messages.testStarted(self.getTestName(test), location=location) - def stopTest(self, test): - start = getattr(test, "startTime", datetime.datetime.now()) - d = datetime.datetime.now() - start - duration=d.microseconds / 1000 + d.seconds * 1000 + d.days * 86400000 - self.messages.testFinished(self.getTestName(test), duration=int(duration)) + def stopTest(self, test): + start = getattr(test, "startTime", datetime.datetime.now()) + d = datetime.datetime.now() - start + duration=d.microseconds / 1000 + d.seconds * 1000 + d.days * 86400000 + self.messages.testFinished(self.getTestName(test), duration=int(duration)) - def endLastSuite(self): - if self.current_suite: - self.messages.testSuiteFinished(self.current_suite) - self.current_suite = None + def endLastSuite(self): + if self.current_suite: + self.messages.testSuiteFinished(self.current_suite) + self.current_suite = None - def _unescape(self, text): - # do not use text.decode('string_escape'), it leads to problems with different string encodings given - return text.replace("\\n", "\n") + def _unescape(self, text): + # do not use text.decode('string_escape'), it leads to problems with different string encodings given + return text.replace("\\n", "\n") class TeamcityTestRunner: - def __init__(self, stream=sys.stdout): - self.stream = stream + def __init__(self, stream=sys.stdout): + self.stream = stream - def _makeResult(self): - return TeamcityTestResult(self.stream) + def _makeResult(self): + return TeamcityTestResult(self.stream) - def run(self, test): - result = self._makeResult() - result.messages.testCount(test.countTestCases()) - test(result) - result.endLastSuite() - return result + def run(self, test): + result = self._makeResult() + result.messages.testCount(test.countTestCases()) + test(result) + result.endLastSuite() + return result