]> granicus.if.org Git - python/commitdiff
Issue #22002: Make full use of test discovery in test sub-packages.
authorZachary Ware <zachary.ware@gmail.com>
Wed, 23 Jul 2014 17:00:29 +0000 (12:00 -0500)
committerZachary Ware <zachary.ware@gmail.com>
Wed, 23 Jul 2014 17:00:29 +0000 (12:00 -0500)
Adds `load_package_tests` function to test.support, uses it in test_asyncio,
test_email, test_json, test_tools, test_importlib and all test_importlib
sub-packages to implement test discovery.

21 files changed:
Doc/library/test.rst
Lib/test/support/__init__.py
Lib/test/test_asyncio/__init__.py
Lib/test/test_asyncio/__main__.py
Lib/test/test_email/__init__.py
Lib/test/test_email/__main__.py
Lib/test/test_importlib/__init__.py
Lib/test/test_importlib/__main__.py
Lib/test/test_importlib/builtin/__init__.py
Lib/test/test_importlib/builtin/__main__.py [new file with mode: 0644]
Lib/test/test_importlib/extension/__init__.py
Lib/test/test_importlib/extension/__main__.py [new file with mode: 0644]
Lib/test/test_importlib/frozen/__init__.py
Lib/test/test_importlib/frozen/__main__.py [new file with mode: 0644]
Lib/test/test_importlib/import_/__init__.py
Lib/test/test_importlib/import_/__main__.py [new file with mode: 0644]
Lib/test/test_importlib/source/__init__.py
Lib/test/test_importlib/source/__main__.py [new file with mode: 0644]
Lib/test/test_json/__init__.py
Lib/test/test_tools/__init__.py
Misc/NEWS

index 83026d85f73295053dd79b48df8cfb83107a8b6a..7a7182a1cbca0715eeb063fd0434e31dcd1c55ce 100644 (file)
@@ -461,7 +461,7 @@ The :mod:`test.support` module defines the following functions:
 .. function:: make_bad_fd()
 
    Create an invalid file descriptor by opening and closing a temporary file,
-   and returning its descripor.
+   and returning its descriptor.
 
 
 .. function:: import_module(name, deprecated=False)
@@ -554,6 +554,21 @@ The :mod:`test.support` module defines the following functions:
    run simultaneously, which is a problem for buildbots.
 
 
+.. function:: load_package_tests(pkg_dir, loader, standard_tests, pattern)
+
+   Generic implementation of the :mod:`unittest` ``load_tests`` protocol for
+   use in test packages.  *pkg_dir* is the root directory of the package;
+   *loader*, *standard_tests*, and *pattern* are the arguments expected by
+   ``load_tests``.  In simple cases, the test package's ``__init__.py``
+   can be the following::
+
+      import os
+      from test.support import load_package_tests
+
+      def load_tests(*args):
+          return load_package_tests(os.path.dirname(__file__), *args)
+
+
 The :mod:`test.support` module defines the following classes:
 
 .. class:: TransientResource(exc, **kwargs)
index 9ec4e7c230b5d4d3430faa8e271f54ad37958c1d..f2c1a92231185df56b357944d02355608d724b5d 100644 (file)
@@ -85,7 +85,7 @@ __all__ = [
     "skip_unless_symlink", "requires_gzip", "requires_bz2", "requires_lzma",
     "bigmemtest", "bigaddrspacetest", "cpython_only", "get_attribute",
     "requires_IEEE_754", "skip_unless_xattr", "requires_zlib",
-    "anticipate_failure",
+    "anticipate_failure", "load_package_tests",
     # sys
     "is_jython", "check_impl_detail",
     # network
@@ -188,6 +188,25 @@ def anticipate_failure(condition):
         return unittest.expectedFailure
     return lambda f: f
 
+def load_package_tests(pkg_dir, loader, standard_tests, pattern):
+    """Generic load_tests implementation for simple test packages.
+
+    Most packages can implement load_tests using this function as follows:
+
+       def load_tests(*args):
+           return load_package_tests(os.path.dirname(__file__), *args)
+    """
+    if pattern is None:
+        pattern = "test*"
+    top_dir = os.path.dirname(              # Lib
+                  os.path.dirname(              # test
+                      os.path.dirname(__file__)))   # support
+    package_tests = loader.discover(start_dir=pkg_dir,
+                                    top_level_dir=top_dir,
+                                    pattern=pattern)
+    standard_tests.addTests(package_tests)
+    return standard_tests
+
 
 def import_fresh_module(name, fresh=(), blocked=(), deprecated=False):
     """Import and return a module, deliberately bypassing sys.modules.
index 82158af77ddcb6b3f44630f4f3d88bbb57c99820..80a9eeaa8ead4e8437781f83643f45752d81eff8 100644 (file)
@@ -1,29 +1,10 @@
 import os
-import sys
-import unittest
-from test.support import run_unittest, import_module
+from test.support import load_package_tests, import_module
 
 # Skip tests if we don't have threading.
 import_module('threading')
 # Skip tests if we don't have concurrent.futures.
 import_module('concurrent.futures')
 
-
-def suite():
-    tests = unittest.TestSuite()
-    loader = unittest.TestLoader()
-    for fn in os.listdir(os.path.dirname(__file__)):
-        if fn.startswith("test") and fn.endswith(".py"):
-            mod_name = 'test.test_asyncio.' + fn[:-3]
-            try:
-                __import__(mod_name)
-            except unittest.SkipTest:
-                pass
-            else:
-                mod = sys.modules[mod_name]
-                tests.addTests(loader.loadTestsFromModule(mod))
-    return tests
-
-
-def test_main():
-    run_unittest(suite())
+def load_tests(*args):
+    return load_package_tests(os.path.dirname(__file__), *args)
index b549492038fb4860e89c0cf4ff9800d26674da49..40a23a297ec2b4f51ce36902fb6af3608b4af0bd 100644 (file)
@@ -1,5 +1,4 @@
-from . import test_main
+from . import load_tests
+import unittest
 
-
-if __name__ == '__main__':
-    test_main()
+unittest.main()
index d8896eed46f5dc62aed7ba4c3bdc175b78f15c65..a59775c4ff59d85425d8c5f0489aaf945f50b793 100644 (file)
@@ -1,31 +1,16 @@
 import os
 import sys
 import unittest
-import test.support
 import collections
 import email
 from email.message import Message
 from email._policybase import compat32
+from test.support import load_package_tests
 from test.test_email import __file__ as landmark
 
-# Run all tests in package for '-m unittest test.test_email'
-def load_tests(loader, standard_tests, pattern):
-    this_dir = os.path.dirname(__file__)
-    if pattern is None:
-        pattern = "test*"
-    package_tests = loader.discover(start_dir=this_dir, pattern=pattern)
-    standard_tests.addTests(package_tests)
-    return standard_tests
-
-
-# used by regrtest and __main__.
-def test_main():
-    here = os.path.dirname(__file__)
-    # Unittest mucks with the path, so we have to save and restore
-    # it to keep regrtest happy.
-    savepath = sys.path[:]
-    test.support._run_suite(unittest.defaultTestLoader.discover(here))
-    sys.path[:] = savepath
+# Load all tests in package
+def load_tests(*args):
+    return load_package_tests(os.path.dirname(__file__), *args)
 
 
 # helper code used by a number of test modules.
index 98af9ecbad3f13a70b63cf6839d9f701b18586d3..4b14f773db42361fe286b9f9abb686f79a36115e 100644 (file)
@@ -1,3 +1,4 @@
-from test.test_email import test_main
+from test.test_email import load_tests
+import unittest
 
-test_main()
+unittest.main()
index 0e345cdc2d40a13fd6e17a1035c82534caf2851b..4b16ecc31156a512db4a28fe272e5339994a4538 100644 (file)
@@ -1,33 +1,5 @@
 import os
-import sys
-from test import support
-import unittest
+from test.support import load_package_tests
 
-def test_suite(package=__package__, directory=os.path.dirname(__file__)):
-    suite = unittest.TestSuite()
-    for name in os.listdir(directory):
-        if name.startswith(('.', '__')):
-            continue
-        path = os.path.join(directory, name)
-        if (os.path.isfile(path) and name.startswith('test_') and
-                name.endswith('.py')):
-            submodule_name = os.path.splitext(name)[0]
-            module_name = "{0}.{1}".format(package, submodule_name)
-            __import__(module_name, level=0)
-            module_tests = unittest.findTestCases(sys.modules[module_name])
-            suite.addTest(module_tests)
-        elif os.path.isdir(path):
-            package_name = "{0}.{1}".format(package, name)
-            __import__(package_name, level=0)
-            package_tests = getattr(sys.modules[package_name], 'test_suite')()
-            suite.addTest(package_tests)
-        else:
-            continue
-    return suite
-
-
-def test_main():
-    start_dir = os.path.dirname(__file__)
-    top_dir = os.path.dirname(os.path.dirname(start_dir))
-    test_loader = unittest.TestLoader()
-    support.run_unittest(test_loader.discover(start_dir, top_level_dir=top_dir))
+def load_tests(*args):
+    return load_package_tests(os.path.dirname(__file__), *args)
index 14bd5bc01722e2c4a16292ac2ae08f307a880be5..40a23a297ec2b4f51ce36902fb6af3608b4af0bd 100644 (file)
@@ -1,9 +1,4 @@
-"""Run importlib's test suite.
+from . import load_tests
+import unittest
 
-Specifying the ``--builtin`` flag will run tests, where applicable, with
-builtins.__import__ instead of importlib.__import__.
-
-"""
-if __name__ == '__main__':
-    from . import test_main
-    test_main()
+unittest.main()
index 15c0ade207e15f0eaf73d9775970401bd29777eb..4b16ecc31156a512db4a28fe272e5339994a4538 100644 (file)
@@ -1,12 +1,5 @@
-from .. import test_suite
 import os
+from test.support import load_package_tests
 
-
-def test_suite():
-    directory = os.path.dirname(__file__)
-    return test_suite('importlib.test.builtin', directory)
-
-
-if __name__ == '__main__':
-    from test.support import run_unittest
-    run_unittest(test_suite())
+def load_tests(*args):
+    return load_package_tests(os.path.dirname(__file__), *args)
diff --git a/Lib/test/test_importlib/builtin/__main__.py b/Lib/test/test_importlib/builtin/__main__.py
new file mode 100644 (file)
index 0000000..40a23a2
--- /dev/null
@@ -0,0 +1,4 @@
+from . import load_tests
+import unittest
+
+unittest.main()
index c0339236fa6143a9526be46c81b89603b8b56dfc..4b16ecc31156a512db4a28fe272e5339994a4538 100644 (file)
@@ -1,13 +1,5 @@
-from .. import test_suite
-import os.path
-import unittest
+import os
+from test.support import load_package_tests
 
-
-def test_suite():
-    directory = os.path.dirname(__file__)
-    return test_suite('importlib.test.extension', directory)
-
-
-if __name__ == '__main__':
-    from test.support import run_unittest
-    run_unittest(test_suite())
+def load_tests(*args):
+    return load_package_tests(os.path.dirname(__file__), *args)
diff --git a/Lib/test/test_importlib/extension/__main__.py b/Lib/test/test_importlib/extension/__main__.py
new file mode 100644 (file)
index 0000000..40a23a2
--- /dev/null
@@ -0,0 +1,4 @@
+from . import load_tests
+import unittest
+
+unittest.main()
index 9ef103bce708c0f223c1d7632c8f90f695347399..4b16ecc31156a512db4a28fe272e5339994a4538 100644 (file)
@@ -1,13 +1,5 @@
-from .. import test_suite
-import os.path
-import unittest
+import os
+from test.support import load_package_tests
 
-
-def test_suite():
-    directory = os.path.dirname(__file__)
-    return test_suite('importlib.test.frozen', directory)
-
-
-if __name__ == '__main__':
-    from test.support import run_unittest
-    run_unittest(test_suite())
+def load_tests(*args):
+    return load_package_tests(os.path.dirname(__file__), *args)
diff --git a/Lib/test/test_importlib/frozen/__main__.py b/Lib/test/test_importlib/frozen/__main__.py
new file mode 100644 (file)
index 0000000..40a23a2
--- /dev/null
@@ -0,0 +1,4 @@
+from . import load_tests
+import unittest
+
+unittest.main()
index 366e53133379dabaec0db9f3ba7bdbe1edc75a16..4b16ecc31156a512db4a28fe272e5339994a4538 100644 (file)
@@ -1,13 +1,5 @@
-from .. import test_suite
-import os.path
-import unittest
+import os
+from test.support import load_package_tests
 
-
-def test_suite():
-    directory = os.path.dirname(__file__)
-    return test_suite('importlib.test.import_', directory)
-
-
-if __name__ == '__main__':
-    from test.support import run_unittest
-    run_unittest(test_suite())
+def load_tests(*args):
+    return load_package_tests(os.path.dirname(__file__), *args)
diff --git a/Lib/test/test_importlib/import_/__main__.py b/Lib/test/test_importlib/import_/__main__.py
new file mode 100644 (file)
index 0000000..40a23a2
--- /dev/null
@@ -0,0 +1,4 @@
+from . import load_tests
+import unittest
+
+unittest.main()
index 3ef97f3aa0398f6afc748c561671de63e2e71aad..4b16ecc31156a512db4a28fe272e5339994a4538 100644 (file)
@@ -1,13 +1,5 @@
-from .. import test_suite
-import os.path
-import unittest
+import os
+from test.support import load_package_tests
 
-
-def test_suite():
-    directory = os.path.dirname(__file__)
-    return test.test_suite('importlib.test.source', directory)
-
-
-if __name__ == '__main__':
-    from test.support import run_unittest
-    run_unittest(test_suite())
+def load_tests(*args):
+    return load_package_tests(os.path.dirname(__file__), *args)
diff --git a/Lib/test/test_importlib/source/__main__.py b/Lib/test/test_importlib/source/__main__.py
new file mode 100644 (file)
index 0000000..40a23a2
--- /dev/null
@@ -0,0 +1,4 @@
+from . import load_tests
+import unittest
+
+unittest.main()
index f994f9b5896b04e53e794ae47fb9387b0f5bd3ee..2cf1032f35aa867906c13987738d148132cbcf06 100644 (file)
@@ -42,23 +42,12 @@ class TestCTest(CTest):
                          '_json')
 
 
-here = os.path.dirname(__file__)
-
-def load_tests(*args):
-    suite = additional_tests()
-    loader = unittest.TestLoader()
-    for fn in os.listdir(here):
-        if fn.startswith("test") and fn.endswith(".py"):
-            modname = "test.test_json." + fn[:-3]
-            __import__(modname)
-            module = sys.modules[modname]
-            suite.addTests(loader.loadTestsFromModule(module))
-    return suite
-
-def additional_tests():
+def load_tests(loader, _, pattern):
     suite = unittest.TestSuite()
     for mod in (json, json.encoder, json.decoder):
         suite.addTest(doctest.DocTestSuite(mod))
     suite.addTest(TestPyTest('test_pyjson'))
     suite.addTest(TestCTest('test_cjson'))
-    return suite
+
+    pkg_dir = os.path.dirname(__file__)
+    return support.load_package_tests(pkg_dir, loader, suite, pattern)
index 9b94cb4483eaa5b9c87800e33614d9676206969c..04c8726e11175265015cd89313e468813a96c088 100644 (file)
@@ -21,11 +21,5 @@ def import_tool(toolname):
     with support.DirsOnSysPath(scriptsdir):
         return importlib.import_module(toolname)
 
-def load_tests(loader, standard_tests, pattern):
-    this_dir = os.path.dirname(__file__)
-    if pattern is None:
-        pattern = "test*"
-    with support.DirsOnSysPath():
-        package_tests = loader.discover(start_dir=this_dir, pattern=pattern)
-    standard_tests.addTests(package_tests)
-    return standard_tests
+def load_tests(*args):
+    return support.load_package_tests(os.path.dirname(__file__), *args)
index 2dc905dcbe4cceec8112fffdaeb54556e5084d81..fedad69aafb3739d222c0b300d6ac9f7ccdd8833 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -209,6 +209,10 @@ IDLE
 Tests
 -----
 
+- Issue #22002: Added ``load_package_tests`` function to test.support and used
+  it to implement/augment test discovery in test_asyncio, test_email,
+  test_importlib, test_json, and test_tools.
+
 - Issue #21976: Fix test_ssl to accept LibreSSL version strings.  Thanks
   to William Orr.