diff -r 1f57839b7b4b Lib/test/support/__init__.py --- a/Lib/test/support/__init__.py Wed Jun 17 10:08:44 2015 -0500 +++ b/Lib/test/support/__init__.py Fri Jun 19 02:59:13 2015 +0200 @@ -26,6 +26,7 @@ import sysconfig import tempfile import time +import types import unittest import urllib.error import warnings @@ -2341,3 +2342,49 @@ "memory allocations") import _testcapi return _testcapi.run_in_subinterp(code) + + +def check__all__(test_instance, module, name_of_module, expected=None, + blacklist=None): + """ + Assert that `module`'s __all__ variable contains all documented names. + + name_of_module must be either a string or iterable of strings. One case for + the latter is when module imports names from its C backend (e.g. ``csv``, + ``_csv``). + + expected can be a initial set of module names, that wouldn't otherwise be + automatically detected as "documented names" (like objects without proper + __module__ attribute). + + blacklist can be a set of names that must not be treated as part of + documented API even though their names indicate otherwise. + + Usage: + import unittest + from test import support + import foo + + class MiscTestCase(unittest.TestCase): + def test__all__(self): + support.check__all__(self, foo, 'foo') + + """ + if isinstance(name_of_module, str): + name_of_module = (name_of_module, ) + + if expected is None: + expected = set() + + if blacklist is None: + blacklist = set() + + for name in dir(module): + if name.startswith('_') or name in blacklist: + continue + module_object = getattr(module, name) + if isinstance(module_object, types.ModuleType): + continue + if getattr(module_object, '__module__', None) in name_of_module: + expected.add(name) + test_instance.assertCountEqual(module.__all__, expected)