Comments (25)
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.
Thank you!
from teamcity-messages.
Updated, slightly as we encountered a slight error with the plugin when running in a parallel test run.
from teamcity-messages.
@shalupov any plan to resolve this?
from teamcity-messages.
@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.
Fwiw, I'm also interested in nose2 support :)
from teamcity-messages.
I too am interested. :)
from teamcity-messages.
+1 )
See number of voters: https://youtrack.jetbrains.com/issue/PY-10465
from teamcity-messages.
+1
from teamcity-messages.
Would be great to have nose2 support.
from teamcity-messages.
+1 this would be very useful in allowing my company to depend on pycharm for more of our development process.
from teamcity-messages.
+1
from teamcity-messages.
+1
from teamcity-messages.
+1
PyCharm support for nose2 please, thank you.
from teamcity-messages.
+1
from teamcity-messages.
+1
from teamcity-messages.
+1
from teamcity-messages.
+1
from teamcity-messages.
+1
from teamcity-messages.
+1
from teamcity-messages.
+1
from teamcity-messages.
Any news?
from teamcity-messages.
@shalupov any news on this?
from teamcity-messages.
+1
from teamcity-messages.
Any updates on this ? cc @mikekidya
from teamcity-messages.
Related Issues (20)
- Wrong file reported when ``assertEquals`` is used with pytest
- Switching expected/actual via swapdiff no longer allowed in pytest.ini
- Release new version HOT 8
- Test suites support for pytest HOT 1
- Playwrigth test execution failed on TeamCity
- test misorganization in heirarchical logs
- `pytest_assertrepr_compare` is ignored in diff HOT 1
- Add ability to use ``repr`` for diffs to show difference between different types
- Problems with default encoding on Windows machines
- Each behave step is considered a test in TeamCity
- Flake8 5.0.0: NotImplementedError: what plugin type? HOT 6
- The flowId attribute in service messages makes tests unable to be nested under a suite
- 1.32: pytest is failing HOT 3
- Could xfail/skip reasons be added to test results?
- The sdist is missing tests
- py.test plugin is incompatible with coverage 7.x HOT 1
- 1.32 fails with pylint >= 2.12 when parallel jobs are enabled
- Roadmap / `ruff` support?
- Error while parsing TeamCity service message: Incorrect property name
- pytest-subtests is breaking the logs HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from teamcity-messages.