Fixed #31509 -- Made DiscoverRunner enable faulthandler by default.

This commit is contained in:
ovkulkarni 2020-05-06 13:52:12 -04:00 committed by Mariusz Felisiak
parent 188f7786bc
commit b7a438c7e2
5 changed files with 61 additions and 3 deletions

View File

@ -1,9 +1,12 @@
import ctypes
import faulthandler
import io
import itertools
import logging
import multiprocessing
import os
import pickle
import sys
import textwrap
import unittest
from importlib import import_module
@ -434,7 +437,7 @@ class DiscoverRunner:
interactive=True, failfast=False, keepdb=False,
reverse=False, debug_mode=False, debug_sql=False, parallel=0,
tags=None, exclude_tags=None, test_name_patterns=None,
pdb=False, buffer=False, **kwargs):
pdb=False, buffer=False, enable_faulthandler=True, **kwargs):
self.pattern = pattern
self.top_level = top_level
@ -448,6 +451,11 @@ class DiscoverRunner:
self.parallel = parallel
self.tags = set(tags or [])
self.exclude_tags = set(exclude_tags or [])
if not faulthandler.is_enabled() and enable_faulthandler:
try:
faulthandler.enable(file=sys.stderr.fileno())
except (AttributeError, io.UnsupportedOperation):
faulthandler.enable(file=sys.__stderr__.fileno())
self.pdb = pdb
if self.pdb and self.parallel > 1:
raise ValueError('You cannot use --pdb with parallel tests; pass --parallel=1 to use it.')
@ -513,6 +521,10 @@ class DiscoverRunner:
'-b', '--buffer', action='store_true',
help='Discard output from passing tests.',
)
parser.add_argument(
'--no-faulthandler', action='store_false', dest='enable_faulthandler',
help='Disables the Python faulthandler module during tests.',
)
if PY37:
parser.add_argument(
'-k', action='append', dest='test_name_patterns',

View File

@ -1515,6 +1515,14 @@ installed, ``ipdb`` is used instead.
Discards output (``stdout`` and ``stderr``) for passing tests, in the same way
as :option:`unittest's --buffer option<unittest.-b>`.
.. django-admin-option:: --no-faulthandler
.. versionadded:: 3.2
Django automatically calls :func:`faulthandler.enable()` when starting the
tests, which allows it to print a traceback if the interpreter crashes. Pass
``--no-faulthandler`` to disable this behavior.
``testserver``
--------------

View File

@ -266,6 +266,10 @@ Tests
creating deep copies with :py:func:`copy.deepcopy`. Assigning objects which
don't support ``deepcopy()`` is deprecated and will be removed in Django 4.1.
* :class:`~django.test.runner.DiscoverRunner` now enables
:py:mod:`faulthandler` by default. This can be disabled by using the
:option:`test --no-faulthandler` option.
* :class:`~django.test.Client` now preserves the request query string when
following 307 and 308 redirects.

View File

@ -510,7 +510,7 @@ behavior. This class defines the ``run_tests()`` entry point, plus a
selection of other methods that are used to by ``run_tests()`` to set up,
execute and tear down the test suite.
.. class:: DiscoverRunner(pattern='test*.py', top_level=None, verbosity=1, interactive=True, failfast=False, keepdb=False, reverse=False, debug_mode=False, debug_sql=False, test_name_patterns=None, pdb=False, buffer=False, **kwargs)
.. class:: DiscoverRunner(pattern='test*.py', top_level=None, verbosity=1, interactive=True, failfast=False, keepdb=False, reverse=False, debug_mode=False, debug_sql=False, test_name_patterns=None, pdb=False, buffer=False, enable_faulthandler=True, **kwargs)
``DiscoverRunner`` will search for tests in any file matching ``pattern``.
@ -557,6 +557,9 @@ execute and tear down the test suite.
If ``buffer`` is ``True``, outputs from passing tests will be discarded.
If ``enable_faulthandler`` is ``True``, :py:mod:`faulthandler` will be
enabled.
Django may, from time to time, extend the capabilities of the test runner
by adding new arguments. The ``**kwargs`` declaration allows for this
expansion. If you subclass ``DiscoverRunner`` or write your own test
@ -571,6 +574,10 @@ execute and tear down the test suite.
The ``buffer`` argument was added.
.. versionadded:: 3.2
The ``enable_faulthandler`` argument was added.
Attributes
~~~~~~~~~~

View File

@ -1,7 +1,9 @@
import os
from argparse import ArgumentParser
from contextlib import contextmanager
from unittest import TestSuite, TextTestRunner, defaultTestLoader, skipUnless
from unittest import (
TestSuite, TextTestRunner, defaultTestLoader, mock, skipUnless,
)
from django.db import connections
from django.test import SimpleTestCase
@ -297,6 +299,31 @@ class DiscoverRunnerTests(SimpleTestCase):
self.assertIn('Write to stderr.', stderr.getvalue())
self.assertIn('Write to stdout.', stdout.getvalue())
@mock.patch('faulthandler.enable')
def test_faulthandler_enabled(self, mocked_enable):
with mock.patch('faulthandler.is_enabled', return_value=False):
DiscoverRunner(enable_faulthandler=True)
mocked_enable.assert_called()
@mock.patch('faulthandler.enable')
def test_faulthandler_already_enabled(self, mocked_enable):
with mock.patch('faulthandler.is_enabled', return_value=True):
DiscoverRunner(enable_faulthandler=True)
mocked_enable.assert_not_called()
@mock.patch('faulthandler.enable')
def test_faulthandler_enabled_fileno(self, mocked_enable):
# sys.stderr that is not an actual file.
with mock.patch('faulthandler.is_enabled', return_value=False), captured_stderr():
DiscoverRunner(enable_faulthandler=True)
mocked_enable.assert_called()
@mock.patch('faulthandler.enable')
def test_faulthandler_disabled(self, mocked_enable):
with mock.patch('faulthandler.is_enabled', return_value=False):
DiscoverRunner(enable_faulthandler=False)
mocked_enable.assert_not_called()
class DiscoverRunnerGetDatabasesTests(SimpleTestCase):
runner = DiscoverRunner(verbosity=2)