Skip to content

Commit

Permalink
JetBrains#236: store diff data it tls, rethraw real exception
Browse files Browse the repository at this point in the history
When custom exception is thrown, stack trace is broken
  • Loading branch information
throwable-one committed Dec 17, 2020
1 parent c76a30c commit 5f4a969
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 8 deletions.
7 changes: 4 additions & 3 deletions teamcity/diff_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@ def _patched_equals(self, first, second, msg=None):
try:
old(self, first, second, msg)
return
except AssertionError as native_error:
except AssertionError:
if not test_filter or test_filter(self):
error = EqualsAssertionError(first, second, msg)
if error.can_be_serialized():
raise error
raise native_error
from .jb_local_exc_store import store_exception
store_exception(error)
raise

unittest.TestCase.assertEqual = _patched_equals

Expand Down
16 changes: 16 additions & 0 deletions teamcity/jb_local_exc_store.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import threading

_JB_PYTEST_LOCAL = threading.local()


def store_exception(exc):
_JB_PYTEST_LOCAL.exception = exc


def get_exception():
try:
exception = _JB_PYTEST_LOCAL.exception
_JB_PYTEST_LOCAL.exception = None
return exception
except AttributeError:
return None
7 changes: 4 additions & 3 deletions teamcity/nose_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,10 @@ def report_fail(self, test, fail_type, err):
details = details[:start_index] + details[end_index + len(_captured_output_end_marker):]

try:
error = err[1]
if isinstance(error, EqualsAssertionError):
details = convert_error_to_string(err, 2)
from .jb_local_exc_store import get_exception
error = get_exception()
if isinstance(err[1], AssertionError) and isinstance(error, EqualsAssertionError):
details = convert_error_to_string(err, 1)
self.messages.testFailed(test_id, message=error.msg, details=details, flowId=test_id, comparison_failure=error)
return
except Exception:
Expand Down
4 changes: 4 additions & 0 deletions teamcity/pytest_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,10 @@ def report_test_failure(self, test_id, report, message=None, report_output=True)
except Exception:
pass

if not diff_error:
from .jb_local_exc_store import get_exception
diff_error = get_exception()

if diff_error:
# Cut everything after postfix: it is internal view of DiffError
strace = str(report.longrepr)
Expand Down
3 changes: 2 additions & 1 deletion teamcity/unittestpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,8 @@ def report_fail(self, test, fail_type, err):

diff_failed = None
try:
error = err[1]
from .jb_local_exc_store import get_exception
error = get_exception()
if isinstance(error, EqualsAssertionError):
diff_failed = error
except Exception:
Expand Down
3 changes: 3 additions & 0 deletions tests/guinea-pigs/pytest/unittest_error_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ def test_error(self):

def test_fail(self):
self.assertTrue(False)

def test_fail_diff(self):
self.assertEqual("A", "B")
6 changes: 5 additions & 1 deletion tests/integration-tests/pytest_integration_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,17 +211,21 @@ def test_unittest_error(venv):
ms = assert_service_messages(
output,
[
ServiceMessage('testCount', {'count': "2"}),
ServiceMessage('testCount', {'count': "3"}),
ServiceMessage('testStarted', {'name': 'tests.guinea-pigs.pytest.unittest_error_test.TestErrorFail.test_error'}),
ServiceMessage('testFailed', {}),
ServiceMessage('testFinished', {'name': 'tests.guinea-pigs.pytest.unittest_error_test.TestErrorFail.test_error'}),
ServiceMessage('testStarted', {'name': 'tests.guinea-pigs.pytest.unittest_error_test.TestErrorFail.test_fail'}),
ServiceMessage('testFailed', {}),
ServiceMessage('testFinished', {'name': 'tests.guinea-pigs.pytest.unittest_error_test.TestErrorFail.test_fail'}),
ServiceMessage('testStarted', {'name': 'tests.guinea-pigs.pytest.unittest_error_test.TestErrorFail.test_fail_diff'}),
ServiceMessage('testFailed', {}),
ServiceMessage('testFinished', {'name': 'tests.guinea-pigs.pytest.unittest_error_test.TestErrorFail.test_fail_diff'}),
])
assert ms[2].params["details"].find("raise Exception") > 0
assert ms[2].params["details"].find("oops") > 0
assert ms[5].params["details"].find("AssertionError") > 0
assert ms[8].params["details"].find("unittest_error_test.py:13") > 0


def test_fixture_error(venv):
Expand Down

0 comments on commit 5f4a969

Please sign in to comment.