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:
Bruno Oliveira 2019-06-22 19:22:43 -03:00
parent a37b902afe
commit 3ce31b6370
4 changed files with 66 additions and 47 deletions

View File

@ -1076,6 +1076,23 @@ passed multiple times. The expected format is ``name=value``. For example::
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

View File

@ -428,11 +428,25 @@ Fault Handler
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.
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.
Also the ``--faulthandler-timeout=X`` can be used to dump the traceback of all threads if a test
takes longer than ``X`` seconds to finish (not available on Windows).
Also the :confval:`faulthandler_timeout=X<faulthandler_timeout>` configuration option can be used
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

View File

@ -6,38 +6,24 @@ import pytest
def pytest_addoption(parser):
group = parser.getgroup("terminal reporting")
group.addoption(
"--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 "
help = (
"Dump the traceback of all threads if a test takes "
"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):
if config.getoption("fault_handler"):
import faulthandler
import faulthandler
# avoid trying to dup sys.stderr if faulthandler is already enabled
if faulthandler.is_enabled():
return
# avoid trying to dup sys.stderr if faulthandler is already enabled
if faulthandler.is_enabled():
return
stderr_fd_copy = os.dup(_get_stderr_fileno())
config.fault_handler_stderr = os.fdopen(stderr_fd_copy, "w")
faulthandler.enable(file=config.fault_handler_stderr)
stderr_fd_copy = os.dup(_get_stderr_fileno())
config.fault_handler_stderr = os.fdopen(stderr_fd_copy, "w")
faulthandler.enable(file=config.fault_handler_stderr)
def _get_stderr_fileno():
@ -51,26 +37,24 @@ def _get_stderr_fileno():
def pytest_unconfigure(config):
if config.getoption("fault_handler"):
import faulthandler
import faulthandler
faulthandler.disable()
# close our dup file installed during pytest_configure
f = getattr(config, "fault_handler_stderr", None)
if f is not None:
# re-enable the faulthandler, attaching it to the default sys.stderr
# so we can see crashes after pytest has finished, usually during
# garbage collection during interpreter shutdown
config.fault_handler_stderr.close()
del config.fault_handler_stderr
faulthandler.enable(file=_get_stderr_fileno())
faulthandler.disable()
# close our dup file installed during pytest_configure
f = getattr(config, "fault_handler_stderr", None)
if f is not None:
# re-enable the faulthandler, attaching it to the default sys.stderr
# so we can see crashes after pytest has finished, usually during
# garbage collection during interpreter shutdown
config.fault_handler_stderr.close()
del config.fault_handler_stderr
faulthandler.enable(file=_get_stderr_fileno())
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_protocol(item):
enabled = item.config.getoption("fault_handler")
timeout = item.config.getoption("fault_handler_timeout")
if enabled and timeout > 0:
timeout = float(item.config.getini("faulthandler_timeout") or 0.0)
if timeout > 0:
import faulthandler
stderr = item.config.fault_handler_stderr

View File

@ -44,7 +44,7 @@ def test_disabled(testdir):
assert not faulthandler.is_enabled()
"""
)
result = testdir.runpytest_subprocess("--no-faulthandler")
result = testdir.runpytest_subprocess("-p", "no:faulthandler")
result.stdout.fnmatch_lines(["*1 passed*"])
assert result.ret == 0
@ -61,9 +61,13 @@ def test_timeout(testdir, enabled):
time.sleep(2.0)
"""
)
args = ["--faulthandler-timeout=1"]
if not enabled:
args.append("--no-faulthandler")
testdir.makeini(
"""
[pytest]
faulthandler_timeout = 1
"""
)
args = ["-p", "no:faulthandler"] if not enabled else []
result = testdir.runpytest_subprocess(*args)
tb_output = "most recent call first"