]> granicus.if.org Git - python/commitdiff
Issue #21918: Convert test_tools.py to a sub-package of test.
authorZachary Ware <zachary.ware@gmail.com>
Wed, 16 Jul 2014 19:26:09 +0000 (14:26 -0500)
committerZachary Ware <zachary.ware@gmail.com>
Wed, 16 Jul 2014 19:26:09 +0000 (14:26 -0500)
Lib/test/test_tools/__init__.py [new file with mode: 0644]
Lib/test/test_tools/__main__.py [new file with mode: 0644]
Lib/test/test_tools/test_gprof2html.py [new file with mode: 0644]
Lib/test/test_tools/test_md5sum.py [new file with mode: 0644]
Lib/test/test_tools/test_pdeps.py [new file with mode: 0644]
Lib/test/test_tools/test_pindent.py [moved from Lib/test/test_tools.py with 56% similarity]
Lib/test/test_tools/test_reindent.py [new file with mode: 0644]
Lib/test/test_tools/test_sundry.py [new file with mode: 0644]
Lib/test/test_tools/test_unparse.py [moved from Tools/parser/test_unparse.py with 95% similarity]
Misc/NEWS

diff --git a/Lib/test/test_tools/__init__.py b/Lib/test/test_tools/__init__.py
new file mode 100644 (file)
index 0000000..9b94cb4
--- /dev/null
@@ -0,0 +1,31 @@
+"""Support functions for testing scripts in the Tools directory."""
+import os
+import unittest
+import importlib
+from test import support
+from fnmatch import fnmatch
+
+basepath = os.path.dirname(                 # <src/install dir>
+                os.path.dirname(                # Lib
+                    os.path.dirname(                # test
+                        os.path.dirname(__file__))))    # test_tools
+
+toolsdir = os.path.join(basepath, 'Tools')
+scriptsdir = os.path.join(toolsdir, 'scripts')
+
+def skip_if_missing():
+    if not os.path.isdir(scriptsdir):
+        raise unittest.SkipTest('scripts directory could not be found')
+
+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
diff --git a/Lib/test/test_tools/__main__.py b/Lib/test/test_tools/__main__.py
new file mode 100644 (file)
index 0000000..b6f13e5
--- /dev/null
@@ -0,0 +1,4 @@
+from test.test_tools import load_tests
+import unittest
+
+unittest.main()
diff --git a/Lib/test/test_tools/test_gprof2html.py b/Lib/test/test_tools/test_gprof2html.py
new file mode 100644 (file)
index 0000000..845a2a8
--- /dev/null
@@ -0,0 +1,36 @@
+"""Tests for the gprof2html script in the Tools directory."""
+
+import os
+import sys
+import importlib
+import unittest
+from unittest import mock
+import tempfile
+
+from test.test_tools import scriptsdir, skip_if_missing, import_tool
+
+skip_if_missing()
+
+class Gprof2htmlTests(unittest.TestCase):
+
+    def setUp(self):
+        self.gprof = import_tool('gprof2html')
+        oldargv = sys.argv
+        def fixup():
+            sys.argv = oldargv
+        self.addCleanup(fixup)
+        sys.argv = []
+
+    def test_gprof(self):
+        # Issue #14508: this used to fail with an NameError.
+        with mock.patch.object(self.gprof, 'webbrowser') as wmock, \
+                tempfile.TemporaryDirectory() as tmpdir:
+            fn = os.path.join(tmpdir, 'abc')
+            open(fn, 'w').close()
+            sys.argv = ['gprof2html', fn]
+            self.gprof.main()
+        self.assertTrue(wmock.open.called)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/Lib/test/test_tools/test_md5sum.py b/Lib/test/test_tools/test_md5sum.py
new file mode 100644 (file)
index 0000000..59ea149
--- /dev/null
@@ -0,0 +1,77 @@
+"""Tests for the md5sum script in the Tools directory."""
+
+import os
+import sys
+import unittest
+from test import support
+from test.script_helper import assert_python_ok, assert_python_failure
+
+from test.test_tools import scriptsdir, import_tool, skip_if_missing
+
+skip_if_missing()
+
+class MD5SumTests(unittest.TestCase):
+    @classmethod
+    def setUpClass(cls):
+        cls.script = os.path.join(scriptsdir, 'md5sum.py')
+        os.mkdir(support.TESTFN)
+        cls.fodder = os.path.join(support.TESTFN, 'md5sum.fodder')
+        with open(cls.fodder, 'wb') as f:
+            f.write(b'md5sum\r\ntest file\r\n')
+        cls.fodder_md5 = b'd38dae2eb1ab346a292ef6850f9e1a0d'
+        cls.fodder_textmode_md5 = b'a8b07894e2ca3f2a4c3094065fa6e0a5'
+
+    @classmethod
+    def tearDownClass(cls):
+        support.rmtree(support.TESTFN)
+
+    def test_noargs(self):
+        rc, out, err = assert_python_ok(self.script)
+        self.assertEqual(rc, 0)
+        self.assertTrue(
+            out.startswith(b'd41d8cd98f00b204e9800998ecf8427e <stdin>'))
+        self.assertFalse(err)
+
+    def test_checksum_fodder(self):
+        rc, out, err = assert_python_ok(self.script, self.fodder)
+        self.assertEqual(rc, 0)
+        self.assertTrue(out.startswith(self.fodder_md5))
+        for part in self.fodder.split(os.path.sep):
+            self.assertIn(part.encode(), out)
+        self.assertFalse(err)
+
+    def test_dash_l(self):
+        rc, out, err = assert_python_ok(self.script, '-l', self.fodder)
+        self.assertEqual(rc, 0)
+        self.assertIn(self.fodder_md5, out)
+        parts = self.fodder.split(os.path.sep)
+        self.assertIn(parts[-1].encode(), out)
+        self.assertNotIn(parts[-2].encode(), out)
+
+    def test_dash_t(self):
+        rc, out, err = assert_python_ok(self.script, '-t', self.fodder)
+        self.assertEqual(rc, 0)
+        self.assertTrue(out.startswith(self.fodder_textmode_md5))
+        self.assertNotIn(self.fodder_md5, out)
+
+    def test_dash_s(self):
+        rc, out, err = assert_python_ok(self.script, '-s', '512', self.fodder)
+        self.assertEqual(rc, 0)
+        self.assertIn(self.fodder_md5, out)
+
+    def test_multiple_files(self):
+        rc, out, err = assert_python_ok(self.script, self.fodder, self.fodder)
+        self.assertEqual(rc, 0)
+        lines = out.splitlines()
+        self.assertEqual(len(lines), 2)
+        self.assertEqual(*lines)
+
+    def test_usage(self):
+        rc, out, err = assert_python_failure(self.script, '-h')
+        self.assertEqual(rc, 2)
+        self.assertEqual(out, b'')
+        self.assertGreater(err, b'')
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/Lib/test/test_tools/test_pdeps.py b/Lib/test/test_tools/test_pdeps.py
new file mode 100644 (file)
index 0000000..091fa6a
--- /dev/null
@@ -0,0 +1,34 @@
+"""Tests for the pdeps script in the Tools directory."""
+
+import os
+import sys
+import unittest
+import tempfile
+from test import support
+
+from test.test_tools import scriptsdir, skip_if_missing, import_tool
+
+skip_if_missing()
+
+
+class PdepsTests(unittest.TestCase):
+
+    @classmethod
+    def setUpClass(self):
+        self.pdeps = import_tool('pdeps')
+
+    def test_process_errors(self):
+        # Issue #14492: m_import.match(line) can be None.
+        with tempfile.TemporaryDirectory() as tmpdir:
+            fn = os.path.join(tmpdir, 'foo')
+            with open(fn, 'w') as stream:
+                stream.write("#!/this/will/fail")
+            self.pdeps.process(fn, {})
+
+    def test_inverse_attribute_error(self):
+        # Issue #14492: this used to fail with an AttributeError.
+        self.pdeps.inverse({'a': []})
+
+
+if __name__ == '__main__':
+    unittest.main()
similarity index 56%
rename from Lib/test/test_tools.py
rename to Lib/test/test_tools/test_pindent.py
index 957dc786f46d62d79edab221a76f593a2d492fd2..14a0aa270f1120c037d40674399def6977876010 100644 (file)
@@ -1,43 +1,16 @@
-"""Tests for scripts in the Tools directory.
-
-This file contains regression tests for some of the scripts found in the
-Tools directory of a Python checkout or tarball, such as reindent.py.
-"""
+"""Tests for the pindent script in the Tools directory."""
 
 import os
 import sys
-import importlib._bootstrap
-import importlib.machinery
 import unittest
-from unittest import mock
-import shutil
 import subprocess
-import sysconfig
-import tempfile
 import textwrap
 from test import support
-from test.script_helper import assert_python_ok, assert_python_failure
-
-if not sysconfig.is_python_build():
-    # XXX some installers do contain the tools, should we detect that
-    # and run the tests in that case too?
-    raise unittest.SkipTest('test irrelevant for an installed Python')
-
-basepath = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))),
-                        'Tools')
-scriptsdir = os.path.join(basepath, 'scripts')
+from test.script_helper import assert_python_ok
 
+from test.test_tools import scriptsdir, skip_if_missing
 
-class ReindentTests(unittest.TestCase):
-    script = os.path.join(scriptsdir, 'reindent.py')
-
-    def test_noargs(self):
-        assert_python_ok(self.script)
-
-    def test_help(self):
-        rc, out, err = assert_python_ok(self.script, '-h')
-        self.assertEqual(out, b'')
-        self.assertGreater(err, b'')
+skip_if_missing()
 
 
 class PindentTests(unittest.TestCase):
@@ -362,162 +335,5 @@ class PindentTests(unittest.TestCase):
         self.pindent_test(clean, closed)
 
 
-class TestSundryScripts(unittest.TestCase):
-    # At least make sure the rest don't have syntax errors.  When tests are
-    # added for a script it should be added to the whitelist below.
-
-    # scripts that have independent tests.
-    whitelist = ['reindent.py', 'pdeps.py', 'gprof2html', 'md5sum.py']
-    # scripts that can't be imported without running
-    blacklist = ['make_ctype.py']
-    # scripts that use windows-only modules
-    windows_only = ['win_add2path.py']
-    # blacklisted for other reasons
-    other = ['analyze_dxp.py']
-
-    skiplist = blacklist + whitelist + windows_only + other
-
-    def setUp(self):
-        cm = support.DirsOnSysPath(scriptsdir)
-        cm.__enter__()
-        self.addCleanup(cm.__exit__)
-
-    def test_sundry(self):
-        for fn in os.listdir(scriptsdir):
-            if fn.endswith('.py') and fn not in self.skiplist:
-                __import__(fn[:-3])
-
-    @unittest.skipIf(sys.platform != "win32", "Windows-only test")
-    def test_sundry_windows(self):
-        for fn in self.windows_only:
-            __import__(fn[:-3])
-
-    @unittest.skipIf(not support.threading, "test requires _thread module")
-    def test_analyze_dxp_import(self):
-        if hasattr(sys, 'getdxp'):
-            import analyze_dxp
-        else:
-            with self.assertRaises(RuntimeError):
-                import analyze_dxp
-
-
-class PdepsTests(unittest.TestCase):
-
-    @classmethod
-    def setUpClass(self):
-        path = os.path.join(scriptsdir, 'pdeps.py')
-        spec = importlib.util.spec_from_file_location('pdeps', path)
-        self.pdeps = importlib._bootstrap._SpecMethods(spec).load()
-
-    @classmethod
-    def tearDownClass(self):
-        if 'pdeps' in sys.modules:
-            del sys.modules['pdeps']
-
-    def test_process_errors(self):
-        # Issue #14492: m_import.match(line) can be None.
-        with tempfile.TemporaryDirectory() as tmpdir:
-            fn = os.path.join(tmpdir, 'foo')
-            with open(fn, 'w') as stream:
-                stream.write("#!/this/will/fail")
-            self.pdeps.process(fn, {})
-
-    def test_inverse_attribute_error(self):
-        # Issue #14492: this used to fail with an AttributeError.
-        self.pdeps.inverse({'a': []})
-
-
-class Gprof2htmlTests(unittest.TestCase):
-
-    def setUp(self):
-        path = os.path.join(scriptsdir, 'gprof2html.py')
-        spec = importlib.util.spec_from_file_location('gprof2html', path)
-        self.gprof = importlib._bootstrap._SpecMethods(spec).load()
-        oldargv = sys.argv
-        def fixup():
-            sys.argv = oldargv
-        self.addCleanup(fixup)
-        sys.argv = []
-
-    def test_gprof(self):
-        # Issue #14508: this used to fail with an NameError.
-        with mock.patch.object(self.gprof, 'webbrowser') as wmock, \
-                tempfile.TemporaryDirectory() as tmpdir:
-            fn = os.path.join(tmpdir, 'abc')
-            open(fn, 'w').close()
-            sys.argv = ['gprof2html', fn]
-            self.gprof.main()
-        self.assertTrue(wmock.open.called)
-
-
-class MD5SumTests(unittest.TestCase):
-
-    @classmethod
-    def setUpClass(cls):
-        cls.script = os.path.join(scriptsdir, 'md5sum.py')
-        os.mkdir(support.TESTFN)
-        cls.fodder = os.path.join(support.TESTFN, 'md5sum.fodder')
-        with open(cls.fodder, 'wb') as f:
-            f.write(b'md5sum\r\ntest file\r\n')
-        cls.fodder_md5 = b'd38dae2eb1ab346a292ef6850f9e1a0d'
-        cls.fodder_textmode_md5 = b'a8b07894e2ca3f2a4c3094065fa6e0a5'
-
-    @classmethod
-    def tearDownClass(cls):
-        support.rmtree(support.TESTFN)
-
-    def test_noargs(self):
-        rc, out, err = assert_python_ok(self.script)
-        self.assertEqual(rc, 0)
-        self.assertTrue(
-            out.startswith(b'd41d8cd98f00b204e9800998ecf8427e <stdin>'))
-        self.assertFalse(err)
-
-    def test_checksum_fodder(self):
-        rc, out, err = assert_python_ok(self.script, self.fodder)
-        self.assertEqual(rc, 0)
-        self.assertTrue(out.startswith(self.fodder_md5))
-        for part in self.fodder.split(os.path.sep):
-            self.assertIn(part.encode(), out)
-        self.assertFalse(err)
-
-    def test_dash_l(self):
-        rc, out, err = assert_python_ok(self.script, '-l', self.fodder)
-        self.assertEqual(rc, 0)
-        self.assertIn(self.fodder_md5, out)
-        parts = self.fodder.split(os.path.sep)
-        self.assertIn(parts[-1].encode(), out)
-        self.assertNotIn(parts[-2].encode(), out)
-
-    def test_dash_t(self):
-        rc, out, err = assert_python_ok(self.script, '-t', self.fodder)
-        self.assertEqual(rc, 0)
-        self.assertTrue(out.startswith(self.fodder_textmode_md5))
-        self.assertNotIn(self.fodder_md5, out)
-
-    def test_dash_s(self):
-        rc, out, err = assert_python_ok(self.script, '-s', '512', self.fodder)
-        self.assertEqual(rc, 0)
-        self.assertIn(self.fodder_md5, out)
-
-    def test_multiple_files(self):
-        rc, out, err = assert_python_ok(self.script, self.fodder, self.fodder)
-        self.assertEqual(rc, 0)
-        lines = out.splitlines()
-        self.assertEqual(len(lines), 2)
-        self.assertEqual(*lines)
-
-    def test_usage(self):
-        rc, out, err = assert_python_failure(self.script, '-h')
-        self.assertEqual(rc, 2)
-        self.assertEqual(out, b'')
-        self.assertGreater(err, b'')
-
-
-# Run the tests in Tools/parser/test_unparse.py
-with support.DirsOnSysPath(os.path.join(basepath, 'parser')):
-    from test_unparse import UnparseTestCase
-    from test_unparse import DirectoryTestCase
-
 if __name__ == '__main__':
     unittest.main()
diff --git a/Lib/test/test_tools/test_reindent.py b/Lib/test/test_tools/test_reindent.py
new file mode 100644 (file)
index 0000000..45cebf7
--- /dev/null
@@ -0,0 +1,28 @@
+"""Tests for scripts in the Tools directory.
+
+This file contains regression tests for some of the scripts found in the
+Tools directory of a Python checkout or tarball, such as reindent.py.
+"""
+
+import os
+import unittest
+from test.script_helper import assert_python_ok
+
+from test.test_tools import scriptsdir, skip_if_missing
+
+skip_if_missing()
+
+class ReindentTests(unittest.TestCase):
+    script = os.path.join(scriptsdir, 'reindent.py')
+
+    def test_noargs(self):
+        assert_python_ok(self.script)
+
+    def test_help(self):
+        rc, out, err = assert_python_ok(self.script, '-h')
+        self.assertEqual(out, b'')
+        self.assertGreater(err, b'')
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/Lib/test/test_tools/test_sundry.py b/Lib/test/test_tools/test_sundry.py
new file mode 100644 (file)
index 0000000..39e541b
--- /dev/null
@@ -0,0 +1,53 @@
+"""Tests for scripts in the Tools directory.
+
+This file contains extremely basic regression tests for the scripts found in
+the Tools directory of a Python checkout or tarball which don't have separate
+tests of their own, such as h2py.py.
+"""
+
+import os
+import sys
+import unittest
+from test import support
+
+from test.test_tools import scriptsdir, import_tool, skip_if_missing
+
+skip_if_missing()
+
+class TestSundryScripts(unittest.TestCase):
+    # At least make sure the rest don't have syntax errors.  When tests are
+    # added for a script it should be added to the whitelist below.
+
+    # scripts that have independent tests.
+    whitelist = ['reindent', 'pdeps', 'gprof2html', 'md5sum']
+    # scripts that can't be imported without running
+    blacklist = ['make_ctype']
+    # scripts that use windows-only modules
+    windows_only = ['win_add2path']
+    # blacklisted for other reasons
+    other = ['analyze_dxp']
+
+    skiplist = blacklist + whitelist + windows_only + other
+
+    def test_sundry(self):
+        for fn in os.listdir(scriptsdir):
+            name = fn[:-3]
+            if fn.endswith('.py') and name not in self.skiplist:
+                import_tool(name)
+
+    @unittest.skipIf(sys.platform != "win32", "Windows-only test")
+    def test_sundry_windows(self):
+        for name in self.windows_only:
+            import_tool(name)
+
+    @unittest.skipIf(not support.threading, "test requires _thread module")
+    def test_analyze_dxp_import(self):
+        if hasattr(sys, 'getdxp'):
+            import_tool('analyze_dxp')
+        else:
+            with self.assertRaises(RuntimeError):
+                import_tool('analyze_dxp')
+
+
+if __name__ == '__main__':
+    unittest.main()
similarity index 95%
rename from Tools/parser/test_unparse.py
rename to Lib/test/test_tools/test_unparse.py
index be84400c38ff3630f42628527dcf8a7094dff360..976a6c59ae10ba61f4f5270d482e6901a615bae6 100644 (file)
@@ -1,12 +1,22 @@
+"""Tests for the unparse.py script in the Tools/parser directory."""
+
 import unittest
 import test.support
 import io
 import os
 import random
 import tokenize
-import unparse
 import ast
 
+from test.test_tools import basepath, toolsdir, skip_if_missing
+
+skip_if_missing()
+
+parser_path = os.path.join(toolsdir, "parser")
+
+with test.support.DirsOnSysPath(parser_path):
+    import unparse
+
 def read_pyfile(filename):
     """Read and return the contents of a Python source file (as a
     string), taking into account the file encoding."""
@@ -249,11 +259,10 @@ class DirectoryTestCase(ASTTestCase):
 
     def test_files(self):
         # get names of files to test
-        dist_dir = os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)
 
         names = []
         for d in self.test_directories:
-            test_dir = os.path.join(dist_dir, d)
+            test_dir = os.path.join(basepath, d)
             for n in os.listdir(test_dir):
                 if n.endswith('.py') and not n.startswith('bad'):
                     names.append(os.path.join(test_dir, n))
@@ -269,8 +278,5 @@ class DirectoryTestCase(ASTTestCase):
             self.check_roundtrip(source)
 
 
-def test_main():
-    test.support.run_unittest(UnparseTestCase, DirectoryTestCase)
-
 if __name__ == '__main__':
-    test_main()
+    unittest.main()
index 1280134debdccdb708fa881cd7b9db20649d5e82..d5715789f46ef9bdf6f32550eb64d7041ea6e6a5 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -198,6 +198,9 @@ IDLE
 Tests
 -----
 
+- Issue #21918: Converted test_tools from a module to a package containing
+  separate test files for each tested script.
+
 - Issue #20155: Changed HTTP method names in failing tests in test_httpservers
   so that packet filtering software (specifically Windows Base Filtering Engine)
   does not interfere with the transaction semantics expected by the tests.