[Python-ideas] Move some regrtest or test.support features into unittest?
Victor Stinner
victor.stinner at gmail.com
Wed Sep 13 09:42:56 EDT 2017
Hi,
tl; dr How can we extend unittest module to plug new checks
before/after running tests?
The CPython project has a big test suite in the Lib/test/ directory.
While all tests are written with the unittest module and the
unittest.TestCase class, tests are not run directly by unittest, but
run by "regrtest" (for "regression test") which is a test runner doing
more checks (and more).
I would like to see if and how we can integrate/move some regrtest
features into the unittest module. Example of regrtest features:
* skip a test if it allocates too much memory, command line argument
to specify how many memory a test is allowed to allocate (ex:
--memlimit=2G for 2 GB of memory)
* concept of "resource" like "network" (connect to external network
servers, to the Internet), "cpu" (CPU intensive tests), etc. Tests are
skipped by default and enabled by the -u command line option (ex: "-u
cpu).
* track memory leaks: check the reference counter, check the number of
allocated memory blocks, check the number of open file descriptors.
* detect if the test spawned a thread or process and the
thread/process is still running at the test exit
* --timeout: watchdog killing the test if the run time exceed the
timeout in seconds (use faulthandler.dump_traceback_later)
* multiprocessing: run tests in subprocesses, in parallel
* redirect stdout/stderr to pipes (StringIO objects), ignore them on
success, or dump them to stdout/stderr on test failure
* --slowest: top 10 of the slowest tests
* --randomize: randomize test order
* --match, --matchfile, -x: filter tests
* --forever: run the test in a loop until it fails (or is interrupted by CTRL+c)
* --list-tests / --list-cases: list test files / test methods
* --fail-env-changed: mark tests as failed if a test altered the environment
* detect if a "global variable" of the standard library was modified
but not restored by the test:
resources = ('sys.argv', 'cwd', 'sys.stdin', 'sys.stdout', 'sys.stderr',
'os.environ', 'sys.path', 'sys.path_hooks', '__import__',
'warnings.filters', 'asyncore.socket_map',
'logging._handlers', 'logging._handlerList', 'sys.gettrace',
'sys.warnoptions',
'multiprocessing.process._dangling', 'threading._dangling',
'sysconfig._CONFIG_VARS', 'sysconfig._INSTALL_SCHEMES',
'files', 'locale', 'warnings.showwarning',
'shutil_archive_formats', 'shutil_unpack_formats',
)
* test.bisect: bisection to identify the failing method, used to track
memory leaks or identify a test leaking a resource (ex: create a file
but don't remove it)
* ... : regrtest has many many features
My question is also connected to test.support
(Lib/test/support/__init__.py): a big module containing a lot of
helper functions to write tests and to detect bugs in tests. For
example, @reap_children decorator emits a warnig if the test leaks a
child process (and reads its exit status to prevent zombie process).
I started to duplicate code in many files of Lib/test/test_*.py to
check if tests "leak running threads" ("dangling threads"). Example
from Lib/test/test_theading.py:
class BaseTestCase(unittest.TestCase):
def setUp(self):
self._threads = test.support.threading_setup()
def tearDown(self):
test.support.threading_cleanup(*self._threads)
test.support.reap_children()
I would like to get this test "for free" directly from the regular
unittest.TestCase class, but I don't know how to extend the unittest
module for that?
Victor
More information about the Python-ideas
mailing list