From 5eb113bae33b05701b8e213d2400298ada29138e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 14 Jul 2019 15:49:48 +0200 Subject: [PATCH] documentation/python: reduce needed test boilerplate. Will do the same for doxygen, plugin and theme tests too, but later. --- documentation/test_python/__init__.py | 32 +++++++++++++++++-- .../test_python/inspect_object/.gitkeep | 0 documentation/test_python/test_content.py | 3 -- documentation/test_python/test_inspect.py | 21 ------------ documentation/test_python/test_layout.py | 3 -- .../test_python/test_link_formatting.py | 5 +-- documentation/test_python/test_page.py | 11 +------ documentation/test_python/test_pybind.py | 18 ----------- 8 files changed, 31 insertions(+), 62 deletions(-) create mode 100644 documentation/test_python/inspect_object/.gitkeep diff --git a/documentation/test_python/__init__.py b/documentation/test_python/__init__.py index 79c69555..92eae451 100644 --- a/documentation/test_python/__init__.py +++ b/documentation/test_python/__init__.py @@ -26,19 +26,43 @@ import copy import sys import os import inspect +import re import shutil import unittest from python import run, default_templates, default_config +# https://stackoverflow.com/a/12867228 +_camelcase_to_snakecase = re.compile('((?<=[a-z0-9])[A-Z]|(?!^)[A-Z](?=[a-z]))') + +# The test files are automatically detected from derived class name and +# filesystem location. For a `test_inspect.NameMapping` class, it will look +# for the `inspect_name_mapping` directory. If the class name is equivalent to +# the filename (e.g. `test_page.Page`), then it will be looking for just `page` +# instead of `page_page`. If needed, the directory name can be overriden by +# passing it via dir to __init__(). class BaseTestCase(unittest.TestCase): - def __init__(self, path, dir, *args, **kwargs): + def __init__(self, *args, dir=None, **kwargs): unittest.TestCase.__init__(self, *args, **kwargs) - # Full directory name (for test_something.py the directory is something_dir{} - self.dirname = os.path.splitext(os.path.basename(path))[0][5:] + ('_' + dir if dir else '') + + # Get the test filename from the derived class module file. If path is + # not supplied, get it from derived class name converted to snake_case + path = sys.modules[self.__class__.__module__].__file__ + if not dir: dir = _camelcase_to_snakecase.sub('_\\1', self.__class__.__name__).lower() + + # Full directory name (for test_something.py the directory is + # something_{dir} + dir_prefix = os.path.splitext(os.path.basename(path))[0][5:] + if dir and dir_prefix != dir: + self.dirname = dir_prefix + '_' + dir + else: + self.dirname = dir_prefix # Absolute path to this directory self.path = os.path.join(os.path.dirname(os.path.realpath(path)), self.dirname) + if not os.path.exists(self.path): + raise AssertionError("autodetected path {} doesn't exist".format(self.path)) + # Display ALL THE DIFFS self.maxDiff = None @@ -72,6 +96,8 @@ class BaseTestCase(unittest.TestCase): actual_contents = f.read().strip() return actual_contents, expected_contents +# On top of the automagic of BaseTestCase this automatically sets INPUT_MODULES +# to detected `dirname`, if not set already. class BaseInspectTestCase(BaseTestCase): def run_python(self, config_overrides={}, templates=default_templates): if 'INPUT_MODULES' not in config_overrides: diff --git a/documentation/test_python/inspect_object/.gitkeep b/documentation/test_python/inspect_object/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/documentation/test_python/test_content.py b/documentation/test_python/test_content.py index e61778a1..8cafecad 100644 --- a/documentation/test_python/test_content.py +++ b/documentation/test_python/test_content.py @@ -27,9 +27,6 @@ import os from . import BaseInspectTestCase class Content(BaseInspectTestCase): - def __init__(self, *args, **kwargs): - super().__init__(__file__, '', *args, **kwargs) - def test(self): self.run_python({ 'PLUGINS': ['m.sphinx'], diff --git a/documentation/test_python/test_inspect.py b/documentation/test_python/test_inspect.py index f28ed0de..c6d76791 100644 --- a/documentation/test_python/test_inspect.py +++ b/documentation/test_python/test_inspect.py @@ -34,9 +34,6 @@ from python import default_templates from . import BaseInspectTestCase class String(BaseInspectTestCase): - def __init__(self, *args, **kwargs): - super().__init__(__file__, 'string', *args, **kwargs) - def test(self): self.run_python({ 'LINKS_NAVBAR1': [ @@ -52,9 +49,6 @@ class String(BaseInspectTestCase): self.assertEqual(*self.actual_expected_contents('modules.html')) class Object(BaseInspectTestCase): - def __init__(self, *args, **kwargs): - super().__init__(__file__, 'object', *args, **kwargs) - def test(self): # Reuse the stuff from inspect_string, but this time reference it via # an object and not a string @@ -77,17 +71,11 @@ class Object(BaseInspectTestCase): self.assertEqual(*self.actual_expected_contents('modules.html', '../inspect_string/modules.html')) class AllProperty(BaseInspectTestCase): - def __init__(self, *args, **kwargs): - super().__init__(__file__, 'all_property', *args, **kwargs) - def test(self): self.run_python() self.assertEqual(*self.actual_expected_contents('inspect_all_property.html')) class Annotations(BaseInspectTestCase): - def __init__(self, *args, **kwargs): - super().__init__(__file__, 'annotations', *args, **kwargs) - def test(self): self.run_python() self.assertEqual(*self.actual_expected_contents('inspect_annotations.html')) @@ -128,9 +116,6 @@ class Annotations(BaseInspectTestCase): self.assertEqual(*self.actual_expected_contents('math.html', 'math36.html')) class NameMapping(BaseInspectTestCase): - def __init__(self, *args, **kwargs): - super().__init__(__file__, 'name_mapping', *args, **kwargs) - def test(self): self.run_python() self.assertEqual(*self.actual_expected_contents('inspect_name_mapping.html')) @@ -138,9 +123,6 @@ class NameMapping(BaseInspectTestCase): self.assertEqual(*self.actual_expected_contents('inspect_name_mapping.submodule.html')) class Recursive(BaseInspectTestCase): - def __init__(self, *args, **kwargs): - super().__init__(__file__, 'recursive', *args, **kwargs) - def test(self): self.run_python() self.assertEqual(*self.actual_expected_contents('inspect_recursive.html')) @@ -148,9 +130,6 @@ class Recursive(BaseInspectTestCase): self.assertEqual(*self.actual_expected_contents('inspect_recursive.a.html')) class TypeLinks(BaseInspectTestCase): - def __init__(self, *args, **kwargs): - super().__init__(__file__, 'type_links', *args, **kwargs) - def test(self): self.run_python() self.assertEqual(*self.actual_expected_contents('inspect_type_links.first.html')) diff --git a/documentation/test_python/test_layout.py b/documentation/test_python/test_layout.py index 0dedeb4f..7a7278ae 100644 --- a/documentation/test_python/test_layout.py +++ b/documentation/test_python/test_layout.py @@ -27,9 +27,6 @@ import os from . import BaseTestCase class Layout(BaseTestCase): - def __init__(self, *args, **kwargs): - super().__init__(__file__, '', *args, **kwargs) - def test(self): self.run_python({ 'PROJECT_TITLE': "A project", diff --git a/documentation/test_python/test_link_formatting.py b/documentation/test_python/test_link_formatting.py index bfc9563e..4623e945 100644 --- a/documentation/test_python/test_link_formatting.py +++ b/documentation/test_python/test_link_formatting.py @@ -60,10 +60,7 @@ def custom_id_formatter(type: EntryType, path: List[str]) -> str: assert False -class Test(BaseInspectTestCase): - def __init__(self, *args, **kwargs): - super().__init__(__file__, '', *args, **kwargs) - +class LinkFormatting(BaseInspectTestCase): def test(self): self.run_python({ 'INPUT_PAGES': ['page.rst'], diff --git a/documentation/test_python/test_page.py b/documentation/test_python/test_page.py index 0dd6a6ec..19ed9f74 100644 --- a/documentation/test_python/test_page.py +++ b/documentation/test_python/test_page.py @@ -35,9 +35,6 @@ def dot_version(): return re.match(".*version (?P\d+\.\d+\.\d+).*", subprocess.check_output(['dot', '-V'], stderr=subprocess.STDOUT).decode('utf-8').strip()).group('version') class Page(BaseTestCase): - def __init__(self, *args, **kwargs): - super().__init__(__file__, '', *args, **kwargs) - def test(self): self.run_python({ 'INPUT_PAGES': ['index.rst', 'another.rst'] @@ -46,10 +43,7 @@ class Page(BaseTestCase): self.assertEqual(*self.actual_expected_contents('another.html')) self.assertEqual(*self.actual_expected_contents('pages.html')) -class PageInputSubdir(BaseTestCase): - def __init__(self, *args, **kwargs): - super().__init__(__file__, 'input_subdir', *args, **kwargs) - +class InputSubdir(BaseTestCase): def test(self): self.run_python({ 'INPUT': 'sub', @@ -59,9 +53,6 @@ class PageInputSubdir(BaseTestCase): self.assertEqual(*self.actual_expected_contents('index.html', '../page/index.html')) class Plugins(BaseTestCase): - def __init__(self, *args, **kwargs): - super().__init__(__file__, 'plugins', *args, **kwargs) - def test(self): self.run_python({ # Test all of them to check the registration works well diff --git a/documentation/test_python/test_pybind.py b/documentation/test_python/test_pybind.py index e2752694..21b5e44e 100644 --- a/documentation/test_python/test_pybind.py +++ b/documentation/test_python/test_pybind.py @@ -174,9 +174,6 @@ class Signature(unittest.TestCase): ('b', 'Tuple[int, module.Bar]', 'Tuple[int, module.Bar]', None)], 'module.Baz')) class Signatures(BaseInspectTestCase): - def __init__(self, *args, **kwargs): - super().__init__(__file__, 'signatures', *args, **kwargs) - def test_positional_args(self): sys.path.append(self.path) import pybind_signatures @@ -217,9 +214,6 @@ class Signatures(BaseInspectTestCase): self.assertEqual(*self.actual_expected_contents('pybind_signatures.MyClass23.html')) class Enums(BaseInspectTestCase): - def __init__(self, *args, **kwargs): - super().__init__(__file__, 'enums', *args, **kwargs) - def test(self): self.run_python({ 'PYBIND11_COMPATIBILITY': True @@ -227,9 +221,6 @@ class Enums(BaseInspectTestCase): self.assertEqual(*self.actual_expected_contents('pybind_enums.html')) class Submodules(BaseInspectTestCase): - def __init__(self, *args, **kwargs): - super().__init__(__file__, 'submodules', *args, **kwargs) - def test(self): self.run_python({ 'PYBIND11_COMPATIBILITY': True @@ -237,9 +228,6 @@ class Submodules(BaseInspectTestCase): self.assertEqual(*self.actual_expected_contents('pybind_submodules.html')) class SubmodulesPackage(BaseInspectTestCase): - def __init__(self, *args, **kwargs): - super().__init__(__file__, 'submodules_package', *args, **kwargs) - def test(self): self.run_python({ 'PYBIND11_COMPATIBILITY': True @@ -247,9 +235,6 @@ class SubmodulesPackage(BaseInspectTestCase): self.assertEqual(*self.actual_expected_contents('pybind_submodules_package.sub.html')) class NameMapping(BaseInspectTestCase): - def __init__(self, *args, **kwargs): - super().__init__(__file__, 'name_mapping', *args, **kwargs) - def test(self): self.run_python({ 'PYBIND11_COMPATIBILITY': True @@ -259,9 +244,6 @@ class NameMapping(BaseInspectTestCase): self.assertEqual(*self.actual_expected_contents('pybind_name_mapping.submodule.html')) class TypeLinks(BaseInspectTestCase): - def __init__(self, *args, **kwargs): - super().__init__(__file__, 'type_links', *args, **kwargs) - def test(self): sys.path.append(self.path) import pybind_type_links -- 2.30.2