Merge pull request #1 from RonnyPfannschmidt/remove-boxed
Remove boxed and provide --boxed via pytest-forked
This commit is contained in:
@@ -22,8 +22,6 @@ test execution modes:
|
|||||||
those for a combined test run. This allows to speed up
|
those for a combined test run. This allows to speed up
|
||||||
development or to use special resources of `remote machines`_.
|
development or to use special resources of `remote machines`_.
|
||||||
|
|
||||||
* ``--boxed``: (not available on Windows) run each test in a boxed_
|
|
||||||
subprocess to survive ``SEGFAULTS`` or otherwise dying processes
|
|
||||||
|
|
||||||
* ``--looponfail``: run your tests repeatedly in a subprocess. After each run
|
* ``--looponfail``: run your tests repeatedly in a subprocess. After each run
|
||||||
py.test waits until a file in your project changes and then re-runs
|
py.test waits until a file in your project changes and then re-runs
|
||||||
|
|||||||
1
changelog/1.removal
Normal file
1
changelog/1.removal
Normal file
@@ -0,0 +1 @@
|
|||||||
|
``--boxed`` functionality has been moved to a separate plugin, `pytest-forked <https://github.com/pytest-dev/pytest-forked>`_. This release now depends on `` pytest-forked`` and provides ``--boxed`` as a backward compatibility option.
|
||||||
@@ -1,3 +1,9 @@
|
|||||||
|
.. note::
|
||||||
|
|
||||||
|
Since 1.19.0, the actual implementation of the ``--boxed`` option has been moved to a
|
||||||
|
separate plugin, `pytest-forked <https://github.com/pytest-dev/pytest-forked>`_
|
||||||
|
which can be installed independently. The ``--boxed`` command-line options remains
|
||||||
|
for backward compatibility reasons.
|
||||||
|
|
||||||
|
|
||||||
If your testing involves C or C++ libraries you might have to deal
|
If your testing involves C or C++ libraries you might have to deal
|
||||||
@@ -19,7 +25,7 @@ to run each test in a controlled subprocess. Here is a basic example::
|
|||||||
|
|
||||||
If you run this with::
|
If you run this with::
|
||||||
|
|
||||||
$ py.test --boxed
|
$ py.test -n1
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux2 -- Python 2.7.3 -- pytest-2.3.0.dev8
|
platform linux2 -- Python 2.7.3 -- pytest-2.3.0.dev8
|
||||||
plugins: xdist, bugzilla, cache, oejskit, cli, pep8, cov
|
plugins: xdist, bugzilla, cache, oejskit, cli, pep8, cov
|
||||||
@@ -40,7 +46,7 @@ You'll see that a couple of tests are reported as crashing, indicated
|
|||||||
by lower-case ``f`` and the respective failure summary. You can also use
|
by lower-case ``f`` and the respective failure summary. You can also use
|
||||||
the xdist-provided parallelization feature to speed up your testing::
|
the xdist-provided parallelization feature to speed up your testing::
|
||||||
|
|
||||||
$ py.test --boxed -n3
|
$ py.test -n3
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
platform linux2 -- Python 2.7.3 -- pytest-2.3.0.dev8
|
platform linux2 -- Python 2.7.3 -- pytest-2.3.0.dev8
|
||||||
plugins: xdist, bugzilla, cache, oejskit, cli, pep8, cov
|
plugins: xdist, bugzilla, cache, oejskit, cli, pep8, cov
|
||||||
|
|||||||
3
setup.py
3
setup.py
@@ -2,7 +2,7 @@ from sys import version_info
|
|||||||
|
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
install_requires = ['execnet>=1.1', 'pytest>=3.0.0']
|
install_requires = ['execnet>=1.1', 'pytest>=3.0.0', 'pytest-forked']
|
||||||
|
|
||||||
if version_info < (2, 7):
|
if version_info < (2, 7):
|
||||||
install_requires.append('ordereddict')
|
install_requires.append('ordereddict')
|
||||||
@@ -24,7 +24,6 @@ setup(
|
|||||||
'pytest11': [
|
'pytest11': [
|
||||||
'xdist = xdist.plugin',
|
'xdist = xdist.plugin',
|
||||||
'xdist.looponfail = xdist.looponfail',
|
'xdist.looponfail = xdist.looponfail',
|
||||||
'xdist.boxed = xdist.boxed',
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
zip_safe=False,
|
zip_safe=False,
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
import pytest
|
|
||||||
import os
|
|
||||||
|
|
||||||
needsfork = pytest.mark.skipif(not hasattr(os, "fork"),
|
|
||||||
reason="os.fork required")
|
|
||||||
|
|
||||||
|
|
||||||
@needsfork
|
|
||||||
def test_functional_boxed(testdir):
|
|
||||||
p1 = testdir.makepyfile("""
|
|
||||||
import os
|
|
||||||
def test_function():
|
|
||||||
os.kill(os.getpid(), 15)
|
|
||||||
""")
|
|
||||||
result = testdir.runpytest(p1, "--boxed")
|
|
||||||
result.stdout.fnmatch_lines([
|
|
||||||
"*CRASHED*",
|
|
||||||
"*1 failed*"
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
@needsfork
|
|
||||||
@pytest.mark.parametrize("capmode", [
|
|
||||||
"no",
|
|
||||||
pytest.mark.xfail("sys", reason="capture cleanup needed"),
|
|
||||||
pytest.mark.xfail("fd", reason="capture cleanup needed")])
|
|
||||||
def test_functional_boxed_capturing(testdir, capmode):
|
|
||||||
p1 = testdir.makepyfile("""
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
def test_function():
|
|
||||||
sys.stdout.write("hello\\n")
|
|
||||||
sys.stderr.write("world\\n")
|
|
||||||
os.kill(os.getpid(), 15)
|
|
||||||
""")
|
|
||||||
result = testdir.runpytest(p1, "--boxed", "--capture=%s" % capmode)
|
|
||||||
result.stdout.fnmatch_lines("""
|
|
||||||
*CRASHED*
|
|
||||||
*stdout*
|
|
||||||
hello
|
|
||||||
*stderr*
|
|
||||||
world
|
|
||||||
*1 failed*
|
|
||||||
""")
|
|
||||||
|
|
||||||
|
|
||||||
class TestOptionEffects:
|
|
||||||
def test_boxed_option_default(self, testdir):
|
|
||||||
tmpdir = testdir.tmpdir.ensure("subdir", dir=1)
|
|
||||||
config = testdir.parseconfig()
|
|
||||||
assert not config.option.boxed
|
|
||||||
pytest.importorskip("execnet")
|
|
||||||
config = testdir.parseconfig('-d', tmpdir)
|
|
||||||
assert not config.option.boxed
|
|
||||||
|
|
||||||
def test_is_not_boxed_by_default(self, testdir):
|
|
||||||
config = testdir.parseconfig(testdir.tmpdir)
|
|
||||||
assert not config.option.boxed
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
|
|
||||||
import py
|
|
||||||
|
|
||||||
|
|
||||||
def pytest_addoption(parser):
|
|
||||||
group = parser.getgroup("xdist", "distributed and subprocess testing")
|
|
||||||
group.addoption(
|
|
||||||
'--boxed',
|
|
||||||
action="store_true", dest="boxed", default=False,
|
|
||||||
help="box each test run in a separate process (unix)")
|
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
from xdist.remote import serialize_report
|
|
||||||
from xdist.slavemanage import unserialize_report
|
|
||||||
|
|
||||||
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
|
|
||||||
@@ -26,10 +26,10 @@ def pytest_addoption(parser):
|
|||||||
help="shortcut for '--dist=load --tx=NUM*popen', "
|
help="shortcut for '--dist=load --tx=NUM*popen', "
|
||||||
"you can use 'auto' here for auto detection CPUs number on "
|
"you can use 'auto' here for auto detection CPUs number on "
|
||||||
"host system")
|
"host system")
|
||||||
group._addoption('--max-slave-restart', action="store", default=None,
|
group.addoption('--max-slave-restart', action="store", default=None,
|
||||||
help="maximum number of slaves that can be restarted "
|
help="maximum number of slaves that can be restarted "
|
||||||
"when crashed (set to zero to disable this feature)")
|
"when crashed (set to zero to disable this feature)")
|
||||||
group._addoption(
|
group.addoption(
|
||||||
'--dist', metavar="distmode",
|
'--dist', metavar="distmode",
|
||||||
action="store", choices=['each', 'load', 'loadscope', 'no'],
|
action="store", choices=['each', 'load', 'loadscope', 'no'],
|
||||||
dest="dist", default="no",
|
dest="dist", default="no",
|
||||||
@@ -40,7 +40,7 @@ def pytest_addoption(parser):
|
|||||||
"loadscope: load balance by sending pending groups of tests in"
|
"loadscope: load balance by sending pending groups of tests in"
|
||||||
" the same scope to any available environment.\n\n"
|
" the same scope to any available environment.\n\n"
|
||||||
"(default) no: run tests inprocess, don't distribute."))
|
"(default) no: run tests inprocess, don't distribute."))
|
||||||
group._addoption(
|
group.addoption(
|
||||||
'--tx', dest="tx", action="append", default=[],
|
'--tx', dest="tx", action="append", default=[],
|
||||||
metavar="xspec",
|
metavar="xspec",
|
||||||
help=("add a test execution environment. some examples: "
|
help=("add a test execution environment. some examples: "
|
||||||
@@ -57,6 +57,9 @@ def pytest_addoption(parser):
|
|||||||
'--rsyncignore', action="append", default=[], metavar="GLOB",
|
'--rsyncignore', action="append", default=[], metavar="GLOB",
|
||||||
help="add expression for ignores when rsyncing to remote tx nodes.")
|
help="add expression for ignores when rsyncing to remote tx nodes.")
|
||||||
|
|
||||||
|
group.addoption(
|
||||||
|
"--boxed", action="store_true",
|
||||||
|
help="backward compatibility alias for pytest-forked --forked")
|
||||||
parser.addini(
|
parser.addini(
|
||||||
'rsyncdirs', 'list of (relative) paths to be rsynced for'
|
'rsyncdirs', 'list of (relative) paths to be rsynced for'
|
||||||
' remote distributed testing.', type="pathlist")
|
' remote distributed testing.', type="pathlist")
|
||||||
@@ -67,6 +70,7 @@ def pytest_addoption(parser):
|
|||||||
"looponfailroots", type="pathlist",
|
"looponfailroots", type="pathlist",
|
||||||
help="directories to check for changes", default=[py.path.local()])
|
help="directories to check for changes", default=[py.path.local()])
|
||||||
|
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
# distributed testing hooks
|
# distributed testing hooks
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
@@ -93,6 +97,8 @@ def pytest_configure(config):
|
|||||||
config.pluginmanager.register(session, "dsession")
|
config.pluginmanager.register(session, "dsession")
|
||||||
tr = config.pluginmanager.getplugin("terminalreporter")
|
tr = config.pluginmanager.getplugin("terminalreporter")
|
||||||
tr.showfspath = False
|
tr.showfspath = False
|
||||||
|
if config.getoption("boxed"):
|
||||||
|
config.option.forked = True
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.tryfirst
|
@pytest.mark.tryfirst
|
||||||
|
|||||||
Reference in New Issue
Block a user