Change pytest-faulthandler for simplification
* The --no-faulthandler option is not necessary given that we can use `-p no:faulthandler`. * The `--faulthandler-timeout` command-line option has become an ini option, for the reasons described in https://github.com/pytest-dev/pytest-faulthandler/issues/34 and users can still set it from the command-line. Fix pytest-dev/pytest-faulthandler#34
This commit is contained in:
parent
a37b902afe
commit
3ce31b6370
|
@ -1076,6 +1076,23 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||||
for more details.
|
for more details.
|
||||||
|
|
||||||
|
|
||||||
|
.. confval:: faulthandler_timeout
|
||||||
|
|
||||||
|
Dumps the tracebacks of all threads if a test takes longer than ``X`` seconds to run (including
|
||||||
|
fixture setup and teardown). Implemented using the `faulthandler.dump_traceback_later`_ function,
|
||||||
|
so all caveats there apply.
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
# content of pytest.ini
|
||||||
|
[pytest]
|
||||||
|
faulthandler_timeout=5
|
||||||
|
|
||||||
|
For more information please refer to :ref:`faulthandler`.
|
||||||
|
|
||||||
|
.. _`faulthandler.dump_traceback_later`: https://docs.python.org/3/library/faulthandler.html#faulthandler.dump_traceback_later
|
||||||
|
|
||||||
|
|
||||||
.. confval:: filterwarnings
|
.. confval:: filterwarnings
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -428,11 +428,25 @@ Fault Handler
|
||||||
The `faulthandler <https://docs.python.org/3/library/faulthandler.html>`__ standard module
|
The `faulthandler <https://docs.python.org/3/library/faulthandler.html>`__ standard module
|
||||||
can be used to dump Python tracebacks on a segfault or after a timeout.
|
can be used to dump Python tracebacks on a segfault or after a timeout.
|
||||||
|
|
||||||
The module is automatically enabled for pytest runs, unless the ``--no-faulthandler`` is given
|
The module is automatically enabled for pytest runs, unless the ``-p no:faulthandler`` is given
|
||||||
on the command-line.
|
on the command-line.
|
||||||
|
|
||||||
Also the ``--faulthandler-timeout=X`` can be used to dump the traceback of all threads if a test
|
Also the :confval:`faulthandler_timeout=X<faulthandler_timeout>` configuration option can be used
|
||||||
takes longer than ``X`` seconds to finish (not available on Windows).
|
to dump the traceback of all threads if a test takes longer than ``X``
|
||||||
|
seconds to finish (not available on Windows).
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
This functionality has been integrated from the external
|
||||||
|
`pytest-faulthandler <https://github.com/pytest-dev/pytest-faulthandler>`__ plugin, with two
|
||||||
|
small differences:
|
||||||
|
|
||||||
|
* To disable it, use ``-p no:faulthandler`` instead of ``--no-faulthandler``: the former
|
||||||
|
can be used with any plugin, so it saves one option.
|
||||||
|
|
||||||
|
* The ``--faulthandler-timeout`` command-line option has become the
|
||||||
|
:confval:`faulthandler_timeout` configuration option. It can still be configured from
|
||||||
|
the command-line using ``-o faulthandler_timeout=X``.
|
||||||
|
|
||||||
|
|
||||||
Creating JUnitXML format files
|
Creating JUnitXML format files
|
||||||
|
|
|
@ -6,38 +6,24 @@ import pytest
|
||||||
|
|
||||||
|
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
group = parser.getgroup("terminal reporting")
|
help = (
|
||||||
group.addoption(
|
"Dump the traceback of all threads if a test takes "
|
||||||
"--no-faulthandler",
|
|
||||||
action="store_false",
|
|
||||||
dest="fault_handler",
|
|
||||||
default=True,
|
|
||||||
help="Disable faulthandler module.",
|
|
||||||
)
|
|
||||||
|
|
||||||
group.addoption(
|
|
||||||
"--faulthandler-timeout",
|
|
||||||
type=float,
|
|
||||||
dest="fault_handler_timeout",
|
|
||||||
metavar="TIMEOUT",
|
|
||||||
default=0.0,
|
|
||||||
help="Dump the traceback of all threads if a test takes "
|
|
||||||
"more than TIMEOUT seconds to finish.\n"
|
"more than TIMEOUT seconds to finish.\n"
|
||||||
"Not available on Windows.",
|
"Not available on Windows."
|
||||||
)
|
)
|
||||||
|
parser.addini("faulthandler_timeout", help, default=0.0)
|
||||||
|
|
||||||
|
|
||||||
def pytest_configure(config):
|
def pytest_configure(config):
|
||||||
if config.getoption("fault_handler"):
|
import faulthandler
|
||||||
import faulthandler
|
|
||||||
|
|
||||||
# avoid trying to dup sys.stderr if faulthandler is already enabled
|
# avoid trying to dup sys.stderr if faulthandler is already enabled
|
||||||
if faulthandler.is_enabled():
|
if faulthandler.is_enabled():
|
||||||
return
|
return
|
||||||
|
|
||||||
stderr_fd_copy = os.dup(_get_stderr_fileno())
|
stderr_fd_copy = os.dup(_get_stderr_fileno())
|
||||||
config.fault_handler_stderr = os.fdopen(stderr_fd_copy, "w")
|
config.fault_handler_stderr = os.fdopen(stderr_fd_copy, "w")
|
||||||
faulthandler.enable(file=config.fault_handler_stderr)
|
faulthandler.enable(file=config.fault_handler_stderr)
|
||||||
|
|
||||||
|
|
||||||
def _get_stderr_fileno():
|
def _get_stderr_fileno():
|
||||||
|
@ -51,26 +37,24 @@ def _get_stderr_fileno():
|
||||||
|
|
||||||
|
|
||||||
def pytest_unconfigure(config):
|
def pytest_unconfigure(config):
|
||||||
if config.getoption("fault_handler"):
|
import faulthandler
|
||||||
import faulthandler
|
|
||||||
|
|
||||||
faulthandler.disable()
|
faulthandler.disable()
|
||||||
# close our dup file installed during pytest_configure
|
# close our dup file installed during pytest_configure
|
||||||
f = getattr(config, "fault_handler_stderr", None)
|
f = getattr(config, "fault_handler_stderr", None)
|
||||||
if f is not None:
|
if f is not None:
|
||||||
# re-enable the faulthandler, attaching it to the default sys.stderr
|
# re-enable the faulthandler, attaching it to the default sys.stderr
|
||||||
# so we can see crashes after pytest has finished, usually during
|
# so we can see crashes after pytest has finished, usually during
|
||||||
# garbage collection during interpreter shutdown
|
# garbage collection during interpreter shutdown
|
||||||
config.fault_handler_stderr.close()
|
config.fault_handler_stderr.close()
|
||||||
del config.fault_handler_stderr
|
del config.fault_handler_stderr
|
||||||
faulthandler.enable(file=_get_stderr_fileno())
|
faulthandler.enable(file=_get_stderr_fileno())
|
||||||
|
|
||||||
|
|
||||||
@pytest.hookimpl(hookwrapper=True)
|
@pytest.hookimpl(hookwrapper=True)
|
||||||
def pytest_runtest_protocol(item):
|
def pytest_runtest_protocol(item):
|
||||||
enabled = item.config.getoption("fault_handler")
|
timeout = float(item.config.getini("faulthandler_timeout") or 0.0)
|
||||||
timeout = item.config.getoption("fault_handler_timeout")
|
if timeout > 0:
|
||||||
if enabled and timeout > 0:
|
|
||||||
import faulthandler
|
import faulthandler
|
||||||
|
|
||||||
stderr = item.config.fault_handler_stderr
|
stderr = item.config.fault_handler_stderr
|
||||||
|
|
|
@ -44,7 +44,7 @@ def test_disabled(testdir):
|
||||||
assert not faulthandler.is_enabled()
|
assert not faulthandler.is_enabled()
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
result = testdir.runpytest_subprocess("--no-faulthandler")
|
result = testdir.runpytest_subprocess("-p", "no:faulthandler")
|
||||||
result.stdout.fnmatch_lines(["*1 passed*"])
|
result.stdout.fnmatch_lines(["*1 passed*"])
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
|
|
||||||
|
@ -61,9 +61,13 @@ def test_timeout(testdir, enabled):
|
||||||
time.sleep(2.0)
|
time.sleep(2.0)
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
args = ["--faulthandler-timeout=1"]
|
testdir.makeini(
|
||||||
if not enabled:
|
"""
|
||||||
args.append("--no-faulthandler")
|
[pytest]
|
||||||
|
faulthandler_timeout = 1
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
args = ["-p", "no:faulthandler"] if not enabled else []
|
||||||
|
|
||||||
result = testdir.runpytest_subprocess(*args)
|
result = testdir.runpytest_subprocess(*args)
|
||||||
tb_output = "most recent call first"
|
tb_output = "most recent call first"
|
||||||
|
|
Loading…
Reference in New Issue