From af2dce50d24fc17ca6ed003c08533756d3a924a4 Mon Sep 17 00:00:00 2001 From: Dima Gerasimov Date: Wed, 7 Aug 2024 00:55:30 +0100 Subject: [PATCH] tests: move more tests into core, more consistent tests running in tox --- my/core/tests/auto_stats.py | 1 + my/core/tests/common.py | 12 +++++ my/core/tests/test_cachew.py | 53 ++++++++++++++++++++ my/core/tests/test_common.py | 54 +++++++++++++++++++++ my/tests/common.py | 2 +- tests/misc.py | 94 ------------------------------------ tox.ini | 10 ++-- 7 files changed, 127 insertions(+), 99 deletions(-) create mode 100644 my/core/tests/common.py create mode 100644 my/core/tests/test_cachew.py create mode 100644 my/core/tests/test_common.py delete mode 100644 tests/misc.py diff --git a/my/core/tests/auto_stats.py b/my/core/tests/auto_stats.py index 2c09b5b4..bf4764cb 100644 --- a/my/core/tests/auto_stats.py +++ b/my/core/tests/auto_stats.py @@ -1,6 +1,7 @@ """ Helper 'module' for test_guess_stats """ + from contextlib import contextmanager from dataclasses import dataclass from datetime import datetime, timedelta diff --git a/my/core/tests/common.py b/my/core/tests/common.py new file mode 100644 index 00000000..d6fb71ef --- /dev/null +++ b/my/core/tests/common.py @@ -0,0 +1,12 @@ +import os + +import pytest + + +V = 'HPI_TESTS_USES_OPTIONAL_DEPS' + +# TODO use it for serialize tests that are using simplejson/orjson? +skip_if_uses_optional_deps = pytest.mark.skipif( + V not in os.environ, + reason=f'test only works when optional dependencies are installed. Set env variable {V}=true to override.', +) diff --git a/my/core/tests/test_cachew.py b/my/core/tests/test_cachew.py new file mode 100644 index 00000000..86344fd4 --- /dev/null +++ b/my/core/tests/test_cachew.py @@ -0,0 +1,53 @@ +from .common import skip_if_uses_optional_deps as pytestmark + +from typing import List + +# TODO ugh, this is very messy.. need to sort out config overriding here + + +def test_cachew() -> None: + from cachew import settings + + settings.ENABLE = True # by default it's off in tests (see conftest.py) + + from my.core.common import mcachew + + called = 0 + + # TODO ugh. need doublewrap or something to avoid having to pass parens + @mcachew() + def cf() -> List[int]: + nonlocal called + called += 1 + return [1, 2, 3] + + list(cf()) + cc = called + # todo ugh. how to clean cache? + # assert called == 1 # precondition, to avoid turdes from previous tests + + assert list(cf()) == [1, 2, 3] + assert called == cc + + +def test_cachew_dir_none() -> None: + from cachew import settings + + settings.ENABLE = True # by default it's off in tests (see conftest.py) + + from my.core.cachew import cache_dir + from my.core.common import mcachew + from my.core.core_config import _reset_config as reset + + with reset() as cc: + cc.cache_dir = None + called = 0 + + @mcachew(cache_path=cache_dir() / 'ctest') + def cf() -> List[int]: + nonlocal called + called += 1 + return [called, called, called] + + assert list(cf()) == [1, 1, 1] + assert list(cf()) == [2, 2, 2] diff --git a/my/core/tests/test_common.py b/my/core/tests/test_common.py new file mode 100644 index 00000000..a2019e4e --- /dev/null +++ b/my/core/tests/test_common.py @@ -0,0 +1,54 @@ +from typing import Iterable, List +import warnings + +from ..common import ( + warn_if_empty, + _warn_iterable, +) + + +def test_warn_if_empty() -> None: + @warn_if_empty + def nonempty() -> Iterable[str]: + yield 'a' + yield 'aba' + + @warn_if_empty + def empty() -> List[int]: + return [] + + # should be rejected by mypy! + # todo how to actually test it? + # @warn_if_empty + # def baad() -> float: + # return 0.00 + + # reveal_type(nonempty) + # reveal_type(empty) + + with warnings.catch_warnings(record=True) as w: + assert list(nonempty()) == ['a', 'aba'] + assert len(w) == 0 + + eee = empty() + assert eee == [] + assert len(w) == 1 + + +def test_warn_iterable() -> None: + i1: List[str] = ['a', 'b'] + i2: Iterable[int] = iter([1, 2, 3]) + # reveal_type(i1) + # reveal_type(i2) + x1 = _warn_iterable(i1) + x2 = _warn_iterable(i2) + # vvvv this should be flagged by mypy + # _warn_iterable(123) + # reveal_type(x1) + # reveal_type(x2) + with warnings.catch_warnings(record=True) as w: + assert x1 is i1 # should be unchanged! + assert len(w) == 0 + + assert list(x2) == [1, 2, 3] + assert len(w) == 0 diff --git a/my/tests/common.py b/my/tests/common.py index c8d88ff2..e3060e15 100644 --- a/my/tests/common.py +++ b/my/tests/common.py @@ -9,7 +9,7 @@ skip_if_not_karlicoss = pytest.mark.skipif( V not in os.environ, - reason=f'test only works on @karlicoss data for now. Set evn variable {V}=true to override.', + reason=f'test only works on @karlicoss data for now. Set env variable {V}=true to override.', ) diff --git a/tests/misc.py b/tests/misc.py deleted file mode 100644 index 7e666d75..00000000 --- a/tests/misc.py +++ /dev/null @@ -1,94 +0,0 @@ -from typing import Iterable, List -import warnings -from my.core import warn_if_empty - - -def test_warn_if_empty() -> None: - @warn_if_empty - def nonempty() -> Iterable[str]: - yield 'a' - yield 'aba' - - @warn_if_empty - def empty() -> List[int]: - return [] - - # should be rejected by mypy! - # todo how to actually test it? - # @warn_if_empty - # def baad() -> float: - # return 0.00 - - # reveal_type(nonempty) - # reveal_type(empty) - - with warnings.catch_warnings(record=True) as w: - assert list(nonempty()) == ['a', 'aba'] - assert len(w) == 0 - - eee = empty() - assert eee == [] - assert len(w) == 1 - - -def test_warn_iterable() -> None: - from my.core.common import _warn_iterable - i1: List[str] = ['a', 'b'] - i2: Iterable[int] = iter([1, 2, 3]) - # reveal_type(i1) - # reveal_type(i2) - x1 = _warn_iterable(i1) - x2 = _warn_iterable(i2) - # vvvv this should be flagged by mypy - # _warn_iterable(123) - # reveal_type(x1) - # reveal_type(x2) - with warnings.catch_warnings(record=True) as w: - assert x1 is i1 # should be unchanged! - assert len(w) == 0 - - assert list(x2) == [1, 2, 3] - assert len(w) == 0 - - -def test_cachew() -> None: - from cachew import settings - settings.ENABLE = True # by default it's off in tests (see conftest.py) - - from my.core.cachew import cache_dir - from my.core.common import mcachew - - called = 0 - # FIXME ugh. need doublewrap or something - @mcachew() - def cf() -> List[int]: - nonlocal called - called += 1 - return [1, 2, 3] - - list(cf()) - cc = called - # todo ugh. how to clean cache? - # assert called == 1 # precondition, to avoid turdes from previous tests - - assert list(cf()) == [1, 2, 3] - assert called == cc - - -def test_cachew_dir_none() -> None: - from cachew import settings - settings.ENABLE = True # by default it's off in tests (see conftest.py) - - from my.core.cachew import cache_dir - from my.core.common import mcachew - from my.core.core_config import _reset_config as reset - with reset() as cc: - cc.cache_dir = None - called = 0 - @mcachew(cache_path=cache_dir() / 'ctest') - def cf() -> List[int]: - nonlocal called - called += 1 - return [called, called, called] - assert list(cf()) == [1, 1, 1] - assert list(cf()) == [2, 2, 2] diff --git a/tox.ini b/tox.ini index 02acdfc8..248469e9 100644 --- a/tox.ini +++ b/tox.ini @@ -48,9 +48,11 @@ commands = # todo maybe also have core tests and misc tests? since ideally want them without dependencies [testenv:tests-all] -# deliberately set to nonexistent path to check the fallback logic -# TODO not sure if need it? -setenv = MY_CONFIG = nonexistent +setenv = + # deliberately set to nonexistent path to check the fallback logic + # TODO not sure if need it? + MY_CONFIG=nonexistent + HPI_TESTS_USES_OPTIONAL_DEPS=true commands = {envpython} -m pip install --use-pep517 -e .[testing] @@ -81,7 +83,7 @@ commands = # importlib is the new suggested import-mode # without it test package names end up as core.tests.* instead of my.core.tests.* --import-mode=importlib \ - --pyargs {[testenv]package_name}.tests \ + --pyargs {[testenv]package_name}.core {[testenv]package_name}.tests \ {posargs} {envpython} -m pytest tests \