Coder Social home page Coder Social logo

Comments (25)

jredl-va avatar jredl-va commented on August 22, 2024

Here is a first cut implementation of one, that is loosely modelled after the nose_report plugin.

# coding=utf-8
import sys
import datetime

from teamcity import is_running_under_teamcity
from teamcity.common import is_string, split_output, limit_output, get_class_fullname, convert_error_to_string
from teamcity.messages import TeamcityServiceMessages

from nose2 import events, result


# from nose.util.ln
def _ln(label):
    label_len = len(label) + 2
    chunk = (70 - label_len) // 2
    out = '%s %s %s' % ('-' * chunk, label, '-' * chunk)
    pad = 70 - len(out)
    if pad > 0:
        out = out + ('-' * pad)
    return out


_captured_output_start_marker = _ln('>> begin captured stdout <<') + "\n"
_captured_output_end_marker = "\n" + _ln('>> end captured stdout <<')

_real_stdout = sys.stdout


class TeamcityReport(events.Plugin):
    alwaysOn = is_running_under_teamcity()
    configSection = 'teamcity-report'
    commandLineSwitch = (None, 'teamcity-report', 'Enable Team City test reporting.')

    def __init__(self):
        self.messages = TeamcityServiceMessages(_real_stdout)
        self.test_started_datetime_map = {}
        self.enabled = False

    def get_test_id(self, test):
        """
        Get a test identifier for the current test
        """
        if is_string(test):
            return test

        test_id = test.id()
        real_test = getattr(test, "test", test)
        real_test_class_name = get_class_fullname(real_test)

        test_arg = getattr(real_test, "arg", tuple())
        if (type(test_arg) is tuple or type(test_arg) is list) and len(test_arg) > 0:
            # As written in nose.case.FunctionTestCase#__str__ or nose.case.MethodTestCase#__str__
            test_arg_str = "%s" % (test_arg,)
            if test_id.endswith(test_arg_str):
                # Replace '.' in test args with '_' to preserve test hierarchy on TeamCity
                test_id = test_id[:len(test_id) - len(test_arg_str)] + test_arg_str.replace('.', '_')

        # Force test_id for doctests
        if real_test_class_name != "doctest.DocTestCase" and real_test_class_name != "nose.plugins.doctests.DocTestCase":
            desc = test.shortDescription()
            if desc and desc != test.id():
                return "%s (%s)" % (test_id, desc.replace('.', '_'))

        return test_id

    def report_fail(self, test, fail_type, err):
        """
        Report a test failure to teamcity
        """
        if is_string(err[2]):
            details = err[2]
        else:
            details = convert_error_to_string(err)

        test_id = self.get_test_id(test)
        start_index = details.find(_captured_output_start_marker)
        end_index = details.find(_captured_output_end_marker)

        if 0 <= start_index < end_index:
            captured_output = details[start_index + len(_captured_output_start_marker):end_index]
            details = details[:start_index] + details[end_index + len(_captured_output_end_marker):]

            for chunk in split_output(limit_output(captured_output)):
                self.messages.testStdOut(test_id, chunk, flowId=test_id)

        self.messages.testFailed(test_id, message=fail_type, details=details, flowId=test_id)

    def reportError(self, event):
        """
        :param event: https://nose2.readthedocs.org/en/latest/dev/event_reference.html#nose2.events.TestOutcomeEvent
        Notify teamcity that an error was encountered running a test.
        """
        test_outcome = event.testEvent
        test_id = self.get_test_id(test_outcome.test)

        if test_outcome.outcome == result.SKIP:
            self.messages.testIgnored(test_id, message="Skipped", flowId=test_id)
        else:
            self.report_fail(test_outcome.test, 'Error', test_outcome.exc_info)

    def reportFailure(self, event):
        """
        :param event: https://nose2.readthedocs.org/en/latest/dev/event_reference.html#nose2.events.TestOutcomeEvent
        Notify teamcity that a test assertion failed.
        """
        self.report_fail(event.testEvent.test, 'Failure', event.testEvent.exc_info)

    def startTest(self, event):
        """
        :param event: https://nose2.readthedocs.org/en/latest/dev/event_reference.html#nose2.events.StartTestRunEvent
        Notify teamcity that a test has started.
        """
        test_id = self.get_test_id(event.test)
        self.test_started_datetime_map[test_id] = event.startTime
        self.messages.testStarted(test_id, captureStandardOutput='true', flowId=test_id)

    def stopTest(self, event):
        """
        :param event: https://nose2.readthedocs.org/en/latest/dev/event_reference.html#nose2.events.StopTestEvent
        Notify teamcity that a test has finished.
        """
        test_id = self.get_test_id(event.test)
        stop_time = datetime.datetime.fromtimestamp(event.stopTime)
        start_time = datetime.datetime.fromtimestamp(self.test_started_datetime_map[test_id])
        self.messages.testFinished(test_id, testDuration=(stop_time - start_time), flowId=test_id)

from teamcity-messages.

shalupov avatar shalupov commented on August 22, 2024

Thank you!

from teamcity-messages.

jredl-va avatar jredl-va commented on August 22, 2024

Updated, slightly as we encountered a slight error with the plugin when running in a parallel test run.

from teamcity-messages.

kaneda avatar kaneda commented on August 22, 2024

@shalupov any plan to resolve this?

from teamcity-messages.

shalupov avatar shalupov commented on August 22, 2024

@kaneda Unfortunately no immediate plan. for proper nose2 support (besides the code above) I need to port/write test suite too and remove code duplication + test it on all supported Python/OS versions. You're the second person who are interested in this, so chances are higher now :)

from teamcity-messages.

mirceapasoi avatar mirceapasoi commented on August 22, 2024

Fwiw, I'm also interested in nose2 support :)

from teamcity-messages.

twm avatar twm commented on August 22, 2024

I too am interested. :)

from teamcity-messages.

throwable-one avatar throwable-one commented on August 22, 2024

+1 )
See number of voters: https://youtrack.jetbrains.com/issue/PY-10465

from teamcity-messages.

eruvanos avatar eruvanos commented on August 22, 2024

+1

from teamcity-messages.

pavelrad avatar pavelrad commented on August 22, 2024

Would be great to have nose2 support.

from teamcity-messages.

peterfine avatar peterfine commented on August 22, 2024

+1 this would be very useful in allowing my company to depend on pycharm for more of our development process.

from teamcity-messages.

Tautvis avatar Tautvis commented on August 22, 2024

+1

from teamcity-messages.

dcartwright avatar dcartwright commented on August 22, 2024

+1

from teamcity-messages.

iamveritas avatar iamveritas commented on August 22, 2024

+1
PyCharm support for nose2 please, thank you.

from teamcity-messages.

EmoBurrito avatar EmoBurrito commented on August 22, 2024

+1

from teamcity-messages.

puruckertom avatar puruckertom commented on August 22, 2024

+1

from teamcity-messages.

fzk-rec avatar fzk-rec commented on August 22, 2024

+1

from teamcity-messages.

howinator avatar howinator commented on August 22, 2024

+1

from teamcity-messages.

kiranjthomas avatar kiranjthomas commented on August 22, 2024

+1

from teamcity-messages.

udelledo avatar udelledo commented on August 22, 2024

+1

from teamcity-messages.

nd842 avatar nd842 commented on August 22, 2024

+1

from teamcity-messages.

nd842 avatar nd842 commented on August 22, 2024

Any news?

from teamcity-messages.

danielhneville avatar danielhneville commented on August 22, 2024

@shalupov any news on this?

from teamcity-messages.

thehiddenwaffle avatar thehiddenwaffle commented on August 22, 2024

+1

from teamcity-messages.

Seluj78 avatar Seluj78 commented on August 22, 2024

Any updates on this ? cc @mikekidya

from teamcity-messages.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.