Repository: cihai/unihan-db (language: python)

Issue:
pyproject(ruff): Add pydocstyle rule selector w/ numpy convention
# Appendix

- https://www.pydocstyle.org/en/stable/
- https://docs.astral.sh/ruff/settings/#pydocstyle


Discussion / hints:

Fix patch:
diff --git a/CHANGES b/CHANGES
index 8af3ca4..1f5da08 100644
--- a/CHANGES
+++ b/CHANGES
@@ -39,6 +39,24 @@ $ pip install --user --upgrade --pre unihan-db
 - Add docstrings to functions, methods, classes, and packages (#322)
 - Split API docs into multiple pages (#328)
 
+### Tests
+
+- Test `examples/` (#324)
+
+  These are high-level integrative tests of the same example code the project
+  uses in documentation.
+
+  This brings code coverage from 69.77 to 93.92%.
+
+  **A note on test times**
+
+  - CI (GitHub Actions) can take 5-6 minutes per test
+
+    This may change in future cases when UNIHAN is cached.
+
+  - Initial (cold) py.tests on local environments won't be cached and will take
+    similar times. Subsequent tests can be <0.6 seconds.
+
 ## unihan-db 0.13.0 (2023-11-19)
 
 ### Packaging
diff --git a/examples/01_bootstrap.py b/examples/01_bootstrap.py
index d7d3e47..7fac5de 100755
--- a/examples/01_bootstrap.py
+++ b/examples/01_bootstrap.py
@@ -1,22 +1,32 @@
 #!/usr/bin/env python
 """Example for bootstrapping UNIHAN DB."""
 import pprint
+import typing as t
 
 from sqlalchemy.sql.expression import func
 
 from unihan_db import bootstrap
 from unihan_db.tables import Unhn
 
-session = bootstrap.get_session()
 
-bootstrap.bootstrap_unihan(session)
+def run(unihan_options: t.Optional[t.Dict[str, object]] = None) -> None:
+    """Initialize Unihan DB via ``bootstrap_unihan()``."""
+    session = bootstrap.get_session()
 
-random_row_query = session.query(Unhn).order_by(func.random()).limit(1)
+    bootstrap.bootstrap_unihan(session)
 
-assert random_row_query is not None
+    random_row_query = session.query(Unhn).order_by(func.random()).limit(1)
 
-random_row = random_row_query.first()
+    assert random_row_query is not None
 
-pprint.pprint(bootstrap.to_dict(random_row))
+    random_row = random_row_query.first()
 
-pprint.pprint(random_row.to_dict())  # type:ignore
+    pprint.pprint(bootstrap.to_dict(random_row))
+
+    assert random_row is not None
+
+    pprint.pprint(random_row.to_dict())  # type:ignore
+
+
+if __name__ == "__main__":
+    run()


Test patch:
diff --git a/tests/test_example.py b/tests/test_example.py
new file mode 100644
index 0000000..afd8c17
--- /dev/null
+++ b/tests/test_example.py
@@ -0,0 +1,45 @@
+"""Test examples/ found in cihai source directory."""
+import importlib
+import importlib.util
+import pathlib
+import sys
+import types
+import typing as t
+
+if t.TYPE_CHECKING:
+    from .types import UnihanOptions
+
+
+class LoadScriptFn(t.Protocol):
+    """Protocol typings for load_script()."""
+
+    def __callable__(
+        self, example: str, project_root: pathlib.Path
+    ) -> types.ModuleType:
+        """Return script as a module."""
+        ...
+
+
+def load_script(example: str, project_root: pathlib.Path) -> types.ModuleType:
+    """Load script as module via name and project root."""
+    file_path = f"{project_root}/examples/{example}.py"
+    module_name = "run"
+
+    spec = importlib.util.spec_from_file_location(module_name, file_path)
+    assert spec is not None
+    module = importlib.util.module_from_spec(spec)
+    sys.modules[module_name] = module
+
+    assert spec.loader is not None
+    spec.loader.exec_module(module)
+
+    return module
+
+
+def test_01_bootstrap(
+    unihan_options: "UnihanOptions",
+    project_root: pathlib.Path,
+) -> None:
+    """Test example dataset."""
+    example = load_script("01_bootstrap", project_root=project_root)
+    example.run()