19
appveyor.yml
19
appveyor.yml
@@ -1,28 +1,13 @@
|
|||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
# note: please use "tox --listenvs" to populate the build matrix
|
# note: please use "tox --listenvs" to populate the build matrix
|
||||||
- TOXENV: "py26-pytest27"
|
|
||||||
- TOXENV: "py26-pytest28"
|
|
||||||
- TOXENV: "py26-pytest29"
|
|
||||||
- TOXENV: "py26-pytest30"
|
- TOXENV: "py26-pytest30"
|
||||||
- TOXENV: "py27-pytest27"
|
|
||||||
- TOXENV: "py27-pytest28"
|
|
||||||
- TOXENV: "py27-pytest29"
|
|
||||||
- TOXENV: "py27-pytest30"
|
- TOXENV: "py27-pytest30"
|
||||||
- TOXENV: "py34-pytest27"
|
|
||||||
- TOXENV: "py34-pytest28"
|
|
||||||
- TOXENV: "py34-pytest29"
|
|
||||||
- TOXENV: "py34-pytest30"
|
- TOXENV: "py34-pytest30"
|
||||||
- TOXENV: "py35-pytest27"
|
|
||||||
- TOXENV: "py35-pytest28"
|
|
||||||
- TOXENV: "py35-pytest29"
|
|
||||||
- TOXENV: "py35-pytest30"
|
- TOXENV: "py35-pytest30"
|
||||||
- TOXENV: "py36-pytest27"
|
|
||||||
- TOXENV: "py36-pytest28"
|
|
||||||
- TOXENV: "py36-pytest29"
|
|
||||||
- TOXENV: "py36-pytest30"
|
- TOXENV: "py36-pytest30"
|
||||||
- TOXENV: "py27-pytest28-pexpect"
|
- TOXENV: "py27-pytest30-pexpect"
|
||||||
- TOXENV: "py35-pytest28-pexpect"
|
- TOXENV: "py35-pytest30-pexpect"
|
||||||
- TOXENV: "flakes"
|
- TOXENV: "flakes"
|
||||||
- TOXENV: "readme"
|
- TOXENV: "readme"
|
||||||
|
|
||||||
|
|||||||
1
changelog/133.bugfix
Normal file
1
changelog/133.bugfix
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Fix serialization and deserialization dropping longrepr details.
|
||||||
2
setup.py
2
setup.py
@@ -20,7 +20,7 @@ setup(
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
zip_safe=False,
|
zip_safe=False,
|
||||||
install_requires=['execnet>=1.1', 'pytest>=2.7.0', 'py>=1.4.22'],
|
install_requires=['execnet>=1.1', 'pytest>=3.0.0', 'py>=1.4.22'],
|
||||||
setup_requires=['setuptools_scm'],
|
setup_requires=['setuptools_scm'],
|
||||||
classifiers=[
|
classifiers=[
|
||||||
'Development Status :: 5 - Production/Stable',
|
'Development Status :: 5 - Production/Stable',
|
||||||
|
|||||||
@@ -268,7 +268,7 @@ class TestFunctional:
|
|||||||
""")
|
""")
|
||||||
child = testdir.spawn_pytest("-f %s" % p)
|
child = testdir.spawn_pytest("-f %s" % p)
|
||||||
child.expect("1 xpass")
|
child.expect("1 xpass")
|
||||||
child.expect("### LOOPONFAILING ####")
|
# child.expect("### LOOPONFAILING ####")
|
||||||
child.expect("waiting for changes")
|
child.expect("waiting for changes")
|
||||||
child.kill(15)
|
child.kill(15)
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,20 @@ def test_remoteinitconfig(testdir):
|
|||||||
|
|
||||||
|
|
||||||
class TestReportSerialization:
|
class TestReportSerialization:
|
||||||
|
def test_xdist_report_longrepr_reprcrash_130(self, testdir):
|
||||||
|
reprec = testdir.inline_runsource("""
|
||||||
|
import py
|
||||||
|
def test_fail(): assert False, 'Expected Message'
|
||||||
|
""")
|
||||||
|
reports = reprec.getreports("pytest_runtest_logreport")
|
||||||
|
assert len(reports) == 3
|
||||||
|
initial_failure_report = reports[1]
|
||||||
|
d = serialize_report(initial_failure_report)
|
||||||
|
check_marshallable(d)
|
||||||
|
processed_report = unserialize_report("testreport", d)
|
||||||
|
assert 'Expected Message' \
|
||||||
|
in processed_report.longrepr.reprcrash.message
|
||||||
|
|
||||||
def test_itemreport_outcomes(self, testdir):
|
def test_itemreport_outcomes(self, testdir):
|
||||||
reprec = testdir.inline_runsource("""
|
reprec = testdir.inline_runsource("""
|
||||||
import py
|
import py
|
||||||
@@ -108,7 +122,7 @@ class TestReportSerialization:
|
|||||||
assert newrep.when == rep.when
|
assert newrep.when == rep.when
|
||||||
assert newrep.keywords == rep.keywords
|
assert newrep.keywords == rep.keywords
|
||||||
if rep.failed:
|
if rep.failed:
|
||||||
assert newrep.longrepr == str(rep.longrepr)
|
assert newrep.longreprtext == rep.longreprtext
|
||||||
|
|
||||||
def test_collectreport_passed(self, testdir):
|
def test_collectreport_passed(self, testdir):
|
||||||
reprec = testdir.inline_runsource("def test_func(): pass")
|
reprec = testdir.inline_runsource("def test_func(): pass")
|
||||||
|
|||||||
7
tox.ini
7
tox.ini
@@ -1,8 +1,8 @@
|
|||||||
[tox]
|
[tox]
|
||||||
# if you change the envlist, please update .travis.yml file as well
|
# if you change the envlist, please update .travis.yml file as well
|
||||||
envlist=
|
envlist=
|
||||||
py{26,27,34,35,36}-pytest{27,28,29,30}
|
py{26,27,34,35,36}-pytest{30}
|
||||||
py{27,35}-pytest28-pexpect
|
py{27,35}-pytest{30}-pexpect
|
||||||
flakes
|
flakes
|
||||||
readme
|
readme
|
||||||
|
|
||||||
@@ -14,9 +14,6 @@ deps =
|
|||||||
pycmd
|
pycmd
|
||||||
# to avoid .eggs
|
# to avoid .eggs
|
||||||
setuptools_scm
|
setuptools_scm
|
||||||
pytest27: pytest~=2.7.2
|
|
||||||
pytest28: pytest~=2.8.7
|
|
||||||
pytest29: pytest~=2.9.2
|
|
||||||
pytest30: pytest~=3.0.5
|
pytest30: pytest~=3.0.5
|
||||||
pexpect: pexpect
|
pexpect: pexpect
|
||||||
platform=
|
platform=
|
||||||
|
|||||||
@@ -98,9 +98,32 @@ class SlaveInteractor:
|
|||||||
|
|
||||||
|
|
||||||
def serialize_report(rep):
|
def serialize_report(rep):
|
||||||
|
def disassembled_report(rep):
|
||||||
|
reprtraceback = rep.longrepr.reprtraceback.__dict__
|
||||||
|
reprcrash = rep.longrepr.reprcrash.__dict__
|
||||||
|
|
||||||
|
new_entries = []
|
||||||
|
for entry in reprtraceback['reprentries']:
|
||||||
|
new_entry = entry.__dict__
|
||||||
|
for key, value in new_entry.items():
|
||||||
|
if hasattr(value, '__dict__'):
|
||||||
|
new_entry[key] = value.__dict__
|
||||||
|
new_entries.append(new_entry)
|
||||||
|
|
||||||
|
reprtraceback['reprentries'] = new_entries
|
||||||
|
|
||||||
|
return {
|
||||||
|
'reprcrash': reprcrash,
|
||||||
|
'reprtraceback': reprtraceback
|
||||||
|
}
|
||||||
|
|
||||||
import py
|
import py
|
||||||
d = rep.__dict__.copy()
|
d = rep.__dict__.copy()
|
||||||
if hasattr(rep.longrepr, 'toterminal'):
|
if hasattr(rep.longrepr, 'toterminal'):
|
||||||
|
if hasattr(rep.longrepr, 'reprtraceback') \
|
||||||
|
and hasattr(rep.longrepr, 'reprcrash'):
|
||||||
|
d['longrepr'] = disassembled_report(rep)
|
||||||
|
else:
|
||||||
d['longrepr'] = str(rep.longrepr)
|
d['longrepr'] = str(rep.longrepr)
|
||||||
else:
|
else:
|
||||||
d['longrepr'] = rep.longrepr
|
d['longrepr'] = rep.longrepr
|
||||||
|
|||||||
@@ -327,7 +327,45 @@ class SlaveController(object):
|
|||||||
|
|
||||||
|
|
||||||
def unserialize_report(name, reportdict):
|
def unserialize_report(name, reportdict):
|
||||||
|
def assembled_report(reportdict):
|
||||||
|
from _pytest._code.code import (
|
||||||
|
ReprExceptionInfo,
|
||||||
|
ReprFileLocation,
|
||||||
|
ReprEntry,
|
||||||
|
ReprFuncArgs,
|
||||||
|
ReprTraceback
|
||||||
|
)
|
||||||
|
if reportdict['longrepr']:
|
||||||
|
if 'reprcrash' and 'reprtraceback' in reportdict['longrepr']:
|
||||||
|
|
||||||
|
reprtraceback = reportdict['longrepr']['reprtraceback']
|
||||||
|
reprcrash = reportdict['longrepr']['reprcrash']
|
||||||
|
|
||||||
|
unserialized_entries = []
|
||||||
|
for entry in reprtraceback['reprentries']:
|
||||||
|
reprfuncargs, reprfileloc = None, None
|
||||||
|
if entry['reprfuncargs']:
|
||||||
|
reprfuncargs = ReprFuncArgs(**entry['reprfuncargs'])
|
||||||
|
if entry['reprfileloc']:
|
||||||
|
reprfileloc = ReprFileLocation(**entry['reprfileloc'])
|
||||||
|
|
||||||
|
reprentry = ReprEntry(
|
||||||
|
lines=entry['lines'],
|
||||||
|
reprfuncargs=reprfuncargs,
|
||||||
|
reprlocals=entry['reprlocals'],
|
||||||
|
filelocrepr=reprfileloc,
|
||||||
|
style=entry['style']
|
||||||
|
)
|
||||||
|
unserialized_entries.append(reprentry)
|
||||||
|
reprtraceback['reprentries'] = unserialized_entries
|
||||||
|
|
||||||
|
reportdict['longrepr'] = ReprExceptionInfo(
|
||||||
|
reprtraceback=ReprTraceback(**reprtraceback),
|
||||||
|
reprcrash=ReprFileLocation(**reprcrash),
|
||||||
|
)
|
||||||
|
return reportdict
|
||||||
|
|
||||||
if name == "testreport":
|
if name == "testreport":
|
||||||
return runner.TestReport(**reportdict)
|
return runner.TestReport(**assembled_report(reportdict))
|
||||||
elif name == "collectreport":
|
elif name == "collectreport":
|
||||||
return runner.CollectReport(**reportdict)
|
return runner.CollectReport(**assembled_report(reportdict))
|
||||||
|
|||||||
Reference in New Issue
Block a user