From 6d53a25962356509a298c9be8360a5697106d770 Mon Sep 17 00:00:00 2001 From: Dima Gerasimov Date: Mon, 21 Oct 2024 20:45:45 +0100 Subject: [PATCH] tests: split into tests-core and tests-all; discover tests from the whole package --- conftest.py | 47 +++++++++++++++++++++++++++++++++ src/promnesia/sources/signal.py | 6 +++++ tox.ini | 28 +++++++++++++++++--- 3 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 conftest.py diff --git a/conftest.py b/conftest.py new file mode 100644 index 00000000..91a43a37 --- /dev/null +++ b/conftest.py @@ -0,0 +1,47 @@ +# this is a hack to monkey patch pytest so it handles tests inside namespace packages without __init__.py properly +# without it, pytest can't discover the package root for some reason +# also see https://github.com/karlicoss/pytest_namespace_pkgs for more + +import os +import pathlib +from typing import Optional + +import _pytest.main +import _pytest.pathlib + +# we consider all dirs in repo/ to be namespace packages +root_dir = pathlib.Path(__file__).absolute().parent.resolve() / 'src' +assert root_dir.exists(), root_dir + +# TODO assert it contains package name?? maybe get it via setuptools.. + +namespace_pkg_dirs = [str(d) for d in root_dir.iterdir() if d.is_dir()] + +# resolve_package_path is called from _pytest.pathlib.import_path +# takes a full abs path to the test file and needs to return the path to the 'root' package on the filesystem +resolve_pkg_path_orig = _pytest.pathlib.resolve_package_path +def resolve_package_path(path: pathlib.Path) -> Optional[pathlib.Path]: + result = path # search from the test file upwards + for parent in result.parents: + if str(parent) in namespace_pkg_dirs: + return parent + if os.name == 'nt': + # ??? for some reason on windows it is trying to call this against conftest? but not on linux/osx + if path.name == 'conftest.py': + return resolve_pkg_path_orig(path) + raise RuntimeError("Couldn't determine path for ", path) +_pytest.pathlib.resolve_package_path = resolve_package_path + + +# without patching, the orig function returns just a package name for some reason +# (I think it's used as a sort of fallback) +# so we need to point it at the absolute path properly +# not sure what are the consequences.. maybe it wouldn't be able to run against installed packages? not sure.. +search_pypath_orig = _pytest.main.search_pypath +def search_pypath(module_name: str) -> str: + mpath = root_dir / module_name.replace('.', os.sep) + if not mpath.is_dir(): + mpath = mpath.with_suffix('.py') + assert mpath.exists(), mpath # just in case + return str(mpath) +_pytest.main.search_pypath = search_pypath diff --git a/src/promnesia/sources/signal.py b/src/promnesia/sources/signal.py index a1e7c556..e5d02bad 100644 --- a/src/promnesia/sources/signal.py +++ b/src/promnesia/sources/signal.py @@ -171,7 +171,10 @@ def _expand_path(path_pattern: PathIsh) -> Iterable[Path]: Expansion code adapted from https://stackoverflow.com/a/51108375/548792 to handle also degenerate cases (``'', '.', '/'``): + """ + # NOTE: suppressing doctest from github actions + """ >>> str(next(iter(_get_files('/')))) '/' @@ -214,7 +217,10 @@ def collect_db_paths(*db_paths: PathIsh, append: bool = False) -> Iterable[Path] one or more pathish Note: needed `append` here, to resolve paths. + """ + # NOTE: suppressing doctest from running on Github actions + """ >>> bool(collect_db_paths()) # my home-path True >>> collect_db_paths(None) diff --git a/tox.ini b/tox.ini index 58b577f2..260df645 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,7 @@ [tox] minversion = 3.21 # relies on the correct version of Python installed -envlist = ruff,tests,mypy-core,mypy-misc +envlist = ruff,tests-core,tests-all,mypy-core,mypy-misc # NOTE: we don't run end2end by default since it requires elaborate setup # https://github.com/tox-dev/tox/issues/20#issuecomment-247788333 # hack to prevent .tox from crapping to the project directory @@ -38,7 +38,20 @@ commands = {envpython} -m ruff check src/ -[testenv:tests] +[testenv:tests-core] +deps = + -e .[testing,markdown] + # NOTE: markdown is only used for test_cli... might be nice to decouple +commands = + {envpython} -m pytest \ + --pyargs {[testenv]package_name} \ + # note: sources are tested in tests-all + --ignore src/promnesia/sources \ + --ignore src/promnesia/tests/sources \ + {posargs} + + +[testenv:tests-all] deps = -e .[testing,all,HPI,org] commands = @@ -46,7 +59,9 @@ commands = {envpython} -m my.core module install \ my.google.takeout.parser \ my.hypothesis - {envpython} -m pytest --pyargs {[testenv]package_name}.tests + {envpython} -m pytest \ + --pyargs {[testenv]package_name} \ + {posargs} [testenv:end2end] @@ -57,7 +72,12 @@ deps = -e .[testing,HPI] commands = {envpython} -m my.core module install my.hypothesis - {envpython} -m pytest tests/end2end_test.py {posargs} + {envpython} -m pytest \ + # TODO noconftest is hack due to end2end tests being in a separate dir + # ideally need to just move it inside the package as well + --noconftest \ + tests/end2end_test.py \ + {posargs} [testenv:mypy-core]