1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
- import py
- from _pytest import runner
- import pytest
- # copied from xdist remote
- def serialize_report(rep):
- import py
- d = rep.__dict__.copy()
- if hasattr(rep.longrepr, 'toterminal'):
- d['longrepr'] = str(rep.longrepr)
- else:
- d['longrepr'] = rep.longrepr
- for name in d:
- if isinstance(d[name], py.path.local):
- d[name] = str(d[name])
- elif name == "result":
- d[name] = None # for now
- return d
- # copied from xdist remote
- def unserialize_report(name, reportdict):
- if name == "testreport":
- return runner.TestReport(**reportdict)
- elif name == "collectreport":
- return runner.CollectReport(**reportdict)
- def pytest_addoption(parser):
- try:
- __import__('xdist.boxed')
- except ImportError:
- # dont register own option if xdist.boxed is availiable
- group = parser.getgroup("boxed", "boxed subprocess test execution")
- group.addoption(
- '--boxed',
- action="store_true", dest="boxed", default=False,
- help="box each test run in a separate process (unix)")
- @pytest.mark.tryfirst
- def pytest_runtest_protocol(item):
- if item.config.getvalue("boxed"):
- reports = forked_run_report(item)
- for rep in reports:
- item.ihook.pytest_runtest_logreport(report=rep)
- return True
- def forked_run_report(item):
- # for now, we run setup/teardown in the subprocess
- # XXX optionally allow sharing of setup/teardown
- from _pytest.runner import runtestprotocol
- EXITSTATUS_TESTEXIT = 4
- import marshal
- def runforked():
- try:
- reports = runtestprotocol(item, log=False)
- except KeyboardInterrupt:
- py.std.os._exit(EXITSTATUS_TESTEXIT)
- return marshal.dumps([serialize_report(x) for x in reports])
- ff = py.process.ForkedFunc(runforked)
- result = ff.waitfinish()
- if result.retval is not None:
- report_dumps = marshal.loads(result.retval)
- return [unserialize_report("testreport", x) for x in report_dumps]
- else:
- if result.exitstatus == EXITSTATUS_TESTEXIT:
- py.test.exit("forked test item %s raised Exit" % (item,))
- return [report_process_crash(item, result)]
- def report_process_crash(item, result):
- path, lineno = item._getfslineno()
- info = ("%s:%s: running the test CRASHED with signal %d" %
- (path, lineno, result.signal))
- from _pytest import runner
- call = runner.CallInfo(lambda: 0/0, "???")
- call.excinfo = info
- rep = runner.pytest_runtest_makereport(item, call)
- if result.out:
- rep.sections.append(("captured stdout", result.out))
- if result.err:
- rep.sections.append(("captured stderr", result.err))
- return rep
|