import sys class TeamcityServiceMessages: quote = {"'": "|'", "|": "||", "\n": "|n", "\r": "|r", ']': '|]', '[': '|['} def __init__(self, output=sys.stdout, prepend_linebreak=False): self.output = output self.prepend_linebreak = prepend_linebreak self.test_stack = [] """ Names of tests """ self.topmost_suite = None """ Last suite we entered in """ self.number_of_tests = 0 def escapeValue(self, value): if sys.version_info[0] <= 2 and isinstance(value, unicode): s = value.encode("utf-8") else: s = str(value) return "".join([self.quote.get(x, x) for x in s]) def message(self, messageName, **properties): s = "##teamcity[" + messageName for k, v in properties.items(): if v is None: continue s = s + " %s='%s'" % (k, self.escapeValue(v)) s += "]\n" if self.prepend_linebreak: self.output.write("\n") self.output.write(s) def testSuiteStarted(self, suiteName, location=None): self.message('testSuiteStarted', name=suiteName, locationHint=location) self.test_stack.append(suiteName) self.topmost_suite = suiteName def testSuiteFinished(self, suiteName): self.message('testSuiteFinished', name=suiteName) self.__pop_current_test() def testStarted(self, testName, location=None, **properties): self.message('testStarted', name=testName, locationHint=location, **properties) self.test_stack.append(testName) self.number_of_tests = self.number_of_tests + 1 def testFinished(self, testName, duration=None, **properties): self.message('testFinished', name=testName, duration=duration, **properties) self.__pop_current_test() def testIgnored(self, testName, message='', **properties): self.message('testIgnored', name=testName, message=message) self.testFinished(testName, **properties) def testFailed(self, testName, message='', details='', expected='', actual='', duration=None, **properties): """ Marks test as failed. *CAUTION*: This method calls ``testFinished``, so you do not need to call it second time. Try to provide ``duration`` if possible. """ if expected and actual: self.message('testFailed', type='comparisonFailure', name=testName, message=message, details=details, expected=expected, actual=actual, **properties) else: self.message('testFailed', name=testName, message=message, details=details, **properties) self.testFinished(testName, int(duration) if duration else None, **properties) def __pop_current_test(self): try: self.test_stack.pop() except IndexError: pass def testError(self, testName, message='', details='', duration=None): self.message('testFailed', name=testName, message=message, details=details, error="true") self.testFinished(testName, int(duration) if duration else None) def current_test_name(self): """ :return: name of current test we are in """ return self.test_stack[-1] if len(self.test_stack) > 0 else None def testStdOut(self, testName, out, **properties): self.message('testStdOut', name=testName, out=out, **properties) def testStdErr(self, testName, out): self.message('testStdErr', name=testName, out=out) def testCount(self, count): self.message('testCount', count=count) def testMatrixEntered(self, **kwargs): self.message('enteredTheMatrix', **kwargs)