summaryrefslogtreecommitdiff
path: root/testing/test_reports.py
diff options
context:
space:
mode:
authorBruno Oliveira <nicoddemus@gmail.com>2020-01-06 21:16:23 -0300
committerBruno Oliveira <nicoddemus@gmail.com>2020-01-06 22:04:38 -0300
commit0e0006934019aba7a3bbec95e2fac7c1b82d1063 (patch)
tree23082977dbe4952b334beddb8249be4d02793846 /testing/test_reports.py
parent26a2e1aba7d9e157b4537bbeb24ad372e8f8b919 (diff)
downloadpytest-0e0006934019aba7a3bbec95e2fac7c1b82d1063.tar.gz
Fix serialization of 'None' reprcrashes
Tracebacks coming from remote processes crated by the multiprocess module will contain "RemoteTracebacks" which don't have a 'reprcrash' attribute Fix #5971
Diffstat (limited to 'testing/test_reports.py')
-rw-r--r--testing/test_reports.py62
1 files changed, 62 insertions, 0 deletions
diff --git a/testing/test_reports.py b/testing/test_reports.py
index ff813543c..f695965e9 100644
--- a/testing/test_reports.py
+++ b/testing/test_reports.py
@@ -305,6 +305,8 @@ class TestReportSerialization:
data = report._to_json()
loaded_report = report_class._from_json(data)
+
+ assert loaded_report.failed
check_longrepr(loaded_report.longrepr)
# make sure we don't blow up on ``toterminal`` call; we don't test the actual output because it is very
@@ -312,6 +314,66 @@ class TestReportSerialization:
# elsewhere and we do check the contents of the longrepr object after loading it.
loaded_report.longrepr.toterminal(tw_mock)
+ def test_chained_exceptions_no_reprcrash(
+ self, testdir, tw_mock,
+ ):
+ """Regression test for tracebacks without a reprcrash (#5971)
+
+ This happens notably on exceptions raised by multiprocess.pool: the exception transfer
+ from subprocess to main process creates an artificial exception which, ExceptionInfo
+ can't obtain the ReprFileLocation from.
+ """
+ testdir.makepyfile(
+ """
+ # equivalent of multiprocessing.pool.RemoteTraceback
+ class RemoteTraceback(Exception):
+ def __init__(self, tb):
+ self.tb = tb
+ def __str__(self):
+ return self.tb
+
+ def test_a():
+ try:
+ raise ValueError('value error')
+ except ValueError as e:
+ # equivalent to how multiprocessing.pool.rebuild_exc does it
+ e.__cause__ = RemoteTraceback('runtime error')
+ raise e
+ """
+ )
+ reprec = testdir.inline_run()
+
+ reports = reprec.getreports("pytest_runtest_logreport")
+
+ def check_longrepr(longrepr):
+ assert isinstance(longrepr, ExceptionChainRepr)
+ assert len(longrepr.chain) == 2
+ entry1, entry2 = longrepr.chain
+ tb1, fileloc1, desc1 = entry1
+ tb2, fileloc2, desc2 = entry2
+
+ assert "RemoteTraceback: runtime error" in str(tb1)
+ assert "ValueError('value error')" in str(tb2)
+
+ assert fileloc1 is None
+ assert fileloc2.message == "ValueError: value error"
+
+ # 3 reports: setup/call/teardown: get the call report
+ assert len(reports) == 3
+ report = reports[1]
+
+ assert report.failed
+ check_longrepr(report.longrepr)
+
+ data = report._to_json()
+ loaded_report = TestReport._from_json(data)
+
+ assert loaded_report.failed
+ check_longrepr(loaded_report.longrepr)
+
+ # for same reasons as previous test, ensure we don't blow up here
+ loaded_report.longrepr.toterminal(tw_mock)
+
class TestHooks:
"""Test that the hooks are working correctly for plugins"""