Issue #241 Make copy during serialization of reprtraceback and reprcrash to avoid mutating.
This commit is contained in:
1
changelog/241.bugfix
Normal file
1
changelog/241.bugfix
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Fix accidental mutation of test report during serialization causing longrepr string-ification to break.
|
||||||
@@ -79,6 +79,21 @@ def test_remoteinitconfig(testdir):
|
|||||||
|
|
||||||
|
|
||||||
class TestReportSerialization:
|
class TestReportSerialization:
|
||||||
|
def test_xdist_longrepr_to_str_issue_241(self, testdir):
|
||||||
|
testdir.makepyfile("""
|
||||||
|
import os
|
||||||
|
def test_a(): assert False
|
||||||
|
def test_b(): pass
|
||||||
|
""")
|
||||||
|
testdir.makeconftest("""
|
||||||
|
def pytest_runtest_logreport(report):
|
||||||
|
print(report.longrepr)
|
||||||
|
""")
|
||||||
|
res = testdir.runpytest('-n1', '-s')
|
||||||
|
res.stdout.fnmatch_lines([
|
||||||
|
'*1 failed, 1 passed *'
|
||||||
|
])
|
||||||
|
|
||||||
def test_xdist_report_longrepr_reprcrash_130(self, testdir):
|
def test_xdist_report_longrepr_reprcrash_130(self, testdir):
|
||||||
reprec = testdir.inline_runsource("""
|
reprec = testdir.inline_runsource("""
|
||||||
import py
|
import py
|
||||||
@@ -107,8 +122,6 @@ class TestReportSerialization:
|
|||||||
assert rep.longrepr.reprtraceback.style \
|
assert rep.longrepr.reprtraceback.style \
|
||||||
== a.longrepr.reprtraceback.style
|
== a.longrepr.reprtraceback.style
|
||||||
assert rep.longrepr.sections == a.longrepr.sections
|
assert rep.longrepr.sections == a.longrepr.sections
|
||||||
assert rep.longrepr.reprtraceback.reprentries \
|
|
||||||
== a.longrepr.reprtraceback.reprentries
|
|
||||||
# Missing section attribute PR171
|
# Missing section attribute PR171
|
||||||
assert added_section in a.longrepr.sections
|
assert added_section in a.longrepr.sections
|
||||||
|
|
||||||
@@ -127,14 +140,15 @@ class TestReportSerialization:
|
|||||||
|
|
||||||
rep_entries = rep.longrepr.reprtraceback.reprentries
|
rep_entries = rep.longrepr.reprtraceback.reprentries
|
||||||
a_entries = a.longrepr.reprtraceback.reprentries
|
a_entries = a.longrepr.reprtraceback.reprentries
|
||||||
assert rep_entries == a_entries
|
|
||||||
for i in range(len(a_entries)):
|
for i in range(len(a_entries)):
|
||||||
assert isinstance(rep_entries[i], ReprEntry)
|
assert isinstance(rep_entries[i], ReprEntry)
|
||||||
assert rep_entries[i].lines == a_entries[i].lines
|
assert rep_entries[i].lines == a_entries[i].lines
|
||||||
assert rep_entries[i].localssep == a_entries[i].localssep
|
assert rep_entries[i].localssep == a_entries[i].localssep
|
||||||
assert rep_entries[i].reprfileloc == a_entries[i].reprfileloc
|
assert rep_entries[i].reprfileloc.lineno == a_entries[i].reprfileloc.lineno
|
||||||
assert rep_entries[i].reprfuncargs == a_entries[i].reprfuncargs
|
assert rep_entries[i].reprfileloc.message == a_entries[i].reprfileloc.message
|
||||||
assert rep_entries[i].reprlocals == a_entries[i].reprlocals
|
assert rep_entries[i].reprfileloc.path == a_entries[i].reprfileloc.path
|
||||||
|
assert rep_entries[i].reprfuncargs.args == a_entries[i].reprfuncargs.args
|
||||||
|
assert rep_entries[i].reprlocals.lines == a_entries[i].reprlocals.lines
|
||||||
assert rep_entries[i].style == a_entries[i].style
|
assert rep_entries[i].style == a_entries[i].style
|
||||||
|
|
||||||
def test_reprentries_serialization_196(self, testdir):
|
def test_reprentries_serialization_196(self, testdir):
|
||||||
@@ -152,7 +166,6 @@ class TestReportSerialization:
|
|||||||
|
|
||||||
rep_entries = rep.longrepr.reprtraceback.reprentries
|
rep_entries = rep.longrepr.reprtraceback.reprentries
|
||||||
a_entries = a.longrepr.reprtraceback.reprentries
|
a_entries = a.longrepr.reprtraceback.reprentries
|
||||||
assert rep_entries == a_entries
|
|
||||||
for i in range(len(a_entries)):
|
for i in range(len(a_entries)):
|
||||||
assert isinstance(rep_entries[i], ReprEntryNative)
|
assert isinstance(rep_entries[i], ReprEntryNative)
|
||||||
assert rep_entries[i].lines == a_entries[i].lines
|
assert rep_entries[i].lines == a_entries[i].lines
|
||||||
|
|||||||
@@ -111,18 +111,18 @@ class SlaveInteractor:
|
|||||||
|
|
||||||
def serialize_report(rep):
|
def serialize_report(rep):
|
||||||
def disassembled_report(rep):
|
def disassembled_report(rep):
|
||||||
reprtraceback = rep.longrepr.reprtraceback.__dict__
|
reprtraceback = rep.longrepr.reprtraceback.__dict__.copy()
|
||||||
reprcrash = rep.longrepr.reprcrash.__dict__
|
reprcrash = rep.longrepr.reprcrash.__dict__.copy()
|
||||||
|
|
||||||
new_entries = []
|
new_entries = []
|
||||||
for entry in reprtraceback['reprentries']:
|
for entry in reprtraceback['reprentries']:
|
||||||
entry_data = {
|
entry_data = {
|
||||||
'type': type(entry).__name__,
|
'type': type(entry).__name__,
|
||||||
'data': entry.__dict__,
|
'data': entry.__dict__.copy(),
|
||||||
}
|
}
|
||||||
for key, value in entry_data['data'].items():
|
for key, value in entry_data['data'].items():
|
||||||
if hasattr(value, '__dict__'):
|
if hasattr(value, '__dict__'):
|
||||||
entry_data['data'][key] = value.__dict__
|
entry_data['data'][key] = value.__dict__.copy()
|
||||||
new_entries.append(entry_data)
|
new_entries.append(entry_data)
|
||||||
|
|
||||||
reprtraceback['reprentries'] = new_entries
|
reprtraceback['reprentries'] = new_entries
|
||||||
|
|||||||
Reference in New Issue
Block a user