From 992053a8f86c5f4abd9aa8bb611bca4d3fcc240a Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Wed, 22 Apr 2026 21:42:42 +0200 Subject: [PATCH] refactor(testing)!: rename simple_module_testing to simple_module_test Renames the pytest-plugin package, its directory, all imports/templates, and the release-workflow PyPI matrix entry. PyPI distribution name becomes simple-module-test (was simple-module-testing). The 0.0.1 CHANGELOG entry is left untouched as a historical record. --- .github/workflows/release.yml | 2 +- conftest.py | 2 +- docs/module-authoring.md | 4 ++-- docs/release.md | 4 ++-- .../hosting/simple_module_hosting/app_builder.py | 2 +- .../hosting/simple_module_hosting/scaffolding.py | 2 +- .../templates/module/pyproject.toml.tpl | 2 +- .../templates/module/tests/test_module.py.tpl | 2 +- framework/testing/README.md | 4 ++-- framework/testing/pyproject.toml | 6 +++--- .../__init__.py | 10 +++++----- .../app_factory.py | 0 .../fake_events.py | 0 .../plugin.py | 6 +++--- .../session_cookie.py | 0 framework/testing/tests/test_app_factory.py | 10 +++++----- framework/testing/tests/test_fake_events.py | 14 +++++++------- modules/background_tasks/tests/test_signals.py | 2 +- modules/users/tests/conftest.py | 2 +- modules/users/tests/test_user_manager.py | 2 +- scripts/loadtest_seed.py | 2 +- tests/benchmarks/test_session_cookie_bench.py | 2 +- tests/integration/conftest.py | 2 +- 23 files changed, 41 insertions(+), 41 deletions(-) rename framework/testing/{simple_module_testing => simple_module_test}/__init__.py (73%) rename framework/testing/{simple_module_testing => simple_module_test}/app_factory.py (100%) rename framework/testing/{simple_module_testing => simple_module_test}/fake_events.py (100%) rename framework/testing/{simple_module_testing => simple_module_test}/plugin.py (78%) rename framework/testing/{simple_module_testing => simple_module_test}/session_cookie.py (100%) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4c155746..3cccd999 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -120,7 +120,7 @@ jobs: - simple_module_core - simple_module_db - simple_module_hosting - - simple_module_testing + - simple_module_test - simple_module_auth - simple_module_background_tasks - simple_module_dashboard diff --git a/conftest.py b/conftest.py index 629d640c..e95e67dc 100644 --- a/conftest.py +++ b/conftest.py @@ -13,7 +13,7 @@ from simple_module_db.base import all_module_bases from simple_module_db.session import DatabaseState, init_db from simple_module_hosting.settings import Settings -from simple_module_testing import forge_session_cookie +from simple_module_test import forge_session_cookie from sqlalchemy.ext.asyncio import ( AsyncEngine, AsyncSession, diff --git a/docs/module-authoring.md b/docs/module-authoring.md index 67d2f280..392ee83a 100644 --- a/docs/module-authoring.md +++ b/docs/module-authoring.md @@ -256,7 +256,7 @@ templates by copying + editing. ## Testing during development -Install `simple_module_testing` as a dev dependency (the `sm create-module` +Install `simple_module_test` as a dev dependency (the `sm create-module` scaffold does this automatically): ```toml @@ -264,7 +264,7 @@ scaffold does this automatically): dev = [ "pytest>=8.0", "pytest-asyncio>=0.24", - "simple_module_testing>=0.1,<1.0", + "simple_module_test>=0.1,<1.0", ] ``` diff --git a/docs/release.md b/docs/release.md index 7cf1313f..74388c89 100644 --- a/docs/release.md +++ b/docs/release.md @@ -41,7 +41,7 @@ Repeat for every project in this list: simple_module_core simple_module_db simple_module_hosting -simple_module_testing +simple_module_test simple_module_auth simple_module_background_tasks simple_module_dashboard @@ -241,7 +241,7 @@ Trusted Publishing is tied to the GitHub repo, not any personal account — so a | PyPI | `simple_module_core` | [framework/core/](../framework/core/) | | PyPI | `simple_module_db` | [framework/db/](../framework/db/) | | PyPI | `simple_module_hosting` | [framework/hosting/](../framework/hosting/) — ships the `sm` / `simple-module` CLI | -| PyPI | `simple_module_testing` | [framework/testing/](../framework/testing/) — pytest plugin | +| PyPI | `simple_module_test` | [framework/testing/](../framework/testing/) — pytest plugin | | PyPI | `simple_module_auth` | [modules/auth/](../modules/auth/) | | PyPI | `simple_module_background_tasks` | [modules/background_tasks/](../modules/background_tasks/) | | PyPI | `simple_module_dashboard` | [modules/dashboard/](../modules/dashboard/) | diff --git a/framework/hosting/simple_module_hosting/app_builder.py b/framework/hosting/simple_module_hosting/app_builder.py index a59754a0..080ab136 100644 --- a/framework/hosting/simple_module_hosting/app_builder.py +++ b/framework/hosting/simple_module_hosting/app_builder.py @@ -69,7 +69,7 @@ def wire_module_routes(app: FastAPI, module) -> None: """Attach a module's API + view routers to ``app`` using its Meta prefixes. The single canonical implementation so ``create_app`` and the test harness - in ``simple_module_testing`` stay in lockstep if ``ModuleBase`` ever gains + in ``simple_module_test`` stay in lockstep if ``ModuleBase`` ever gains a new router type. """ api_router = APIRouter(prefix=module.meta.route_prefix, tags=[module.meta.name]) diff --git a/framework/hosting/simple_module_hosting/scaffolding.py b/framework/hosting/simple_module_hosting/scaffolding.py index 040e9068..a5892ebf 100644 --- a/framework/hosting/simple_module_hosting/scaffolding.py +++ b/framework/hosting/simple_module_hosting/scaffolding.py @@ -206,7 +206,7 @@ def create_module( f"simple_module_dashboard=={_FRAMEWORK_VERSION}", f"simple_module_permissions=={_FRAMEWORK_VERSION}", ] -_APP_PY_DEV_DEPS = [f"simple_module_testing=={_FRAMEWORK_VERSION}", "pytest>=8.0"] +_APP_PY_DEV_DEPS = [f"simple_module_test=={_FRAMEWORK_VERSION}", "pytest>=8.0"] _APP_NPM_DEPS = { "@simple-module-py/ui": _FRAMEWORK_VERSION, diff --git a/framework/hosting/simple_module_hosting/templates/module/pyproject.toml.tpl b/framework/hosting/simple_module_hosting/templates/module/pyproject.toml.tpl index 1085da22..edb2072f 100644 --- a/framework/hosting/simple_module_hosting/templates/module/pyproject.toml.tpl +++ b/framework/hosting/simple_module_hosting/templates/module/pyproject.toml.tpl @@ -19,7 +19,7 @@ dev = [ "pytest-asyncio>=0.24", # Shared fixtures (fake_event_bus, build_test_app, etc.) for testing # modules in isolation. The pytest11 entry_point auto-registers them. - "simple_module_testing>=0.1,<1.0", + "simple_module_test>=0.1,<1.0", ] [build-system] diff --git a/framework/hosting/simple_module_hosting/templates/module/tests/test_module.py.tpl b/framework/hosting/simple_module_hosting/templates/module/tests/test_module.py.tpl index 7609850f..ec3e5e6c 100644 --- a/framework/hosting/simple_module_hosting/templates/module/tests/test_module.py.tpl +++ b/framework/hosting/simple_module_hosting/templates/module/tests/test_module.py.tpl @@ -1,7 +1,7 @@ """Smoke tests for the {{MODULE_NAME}} module. The ``build_test_app`` and ``fake_event_bus`` fixtures come from the -``simple_module_testing`` pytest plugin (registered via entry_points when +``simple_module_test`` pytest plugin (registered via entry_points when that package is installed). No conftest.py is required. """ diff --git a/framework/testing/README.md b/framework/testing/README.md index 83b1ffe2..90c0b6d2 100644 --- a/framework/testing/README.md +++ b/framework/testing/README.md @@ -1,4 +1,4 @@ -# simple_module_testing +# simple_module_test Shared pytest fixtures and helpers for writing tests against [simple_module](https://github.com/antosubash/simple_module_python) apps and modules. @@ -7,7 +7,7 @@ Fixtures are exposed via a `pytest11` entry point, so installing the package is ## Install ```bash -pip install simple_module_testing +pip install simple_module_test # or, if you already pulled in the framework: pip install "simple_module_hosting[dev]" ``` diff --git a/framework/testing/pyproject.toml b/framework/testing/pyproject.toml index 69d18f2e..192d7a04 100644 --- a/framework/testing/pyproject.toml +++ b/framework/testing/pyproject.toml @@ -1,5 +1,5 @@ [project] -name = "simple_module_testing" +name = "simple_module_test" version = "0.0.1" description = "Shared pytest fixtures (app, client, db_session, authenticated_client) for writing simple_module module tests" readme = "README.md" @@ -32,7 +32,7 @@ dependencies = [ ] [project.entry-points.pytest11] -simple_module_testing = "simple_module_testing.plugin" +simple_module_test = "simple_module_test.plugin" [project.urls] Homepage = "https://github.com/antosubash/simple_module_python" @@ -45,7 +45,7 @@ requires = ["hatchling"] build-backend = "hatchling.build" [tool.hatch.build.targets.wheel] -packages = ["simple_module_testing"] +packages = ["simple_module_test"] [tool.uv.sources] simple_module_core = { workspace = true } diff --git a/framework/testing/simple_module_testing/__init__.py b/framework/testing/simple_module_test/__init__.py similarity index 73% rename from framework/testing/simple_module_testing/__init__.py rename to framework/testing/simple_module_test/__init__.py index 95f4e483..6535bc99 100644 --- a/framework/testing/simple_module_testing/__init__.py +++ b/framework/testing/simple_module_test/__init__.py @@ -1,6 +1,6 @@ """Shared pytest fixtures and helpers for SimpleModule module authors. -Install with ``pip install simple_module_testing[dev]`` (or add it to +Install with ``pip install simple_module_test[dev]`` (or add it to ``[project.optional-dependencies].dev`` of your module). The pytest plugin registers its fixtures automatically via the ``pytest11`` entry_point — no imports needed in your test files. @@ -13,13 +13,13 @@ one module, with an in-memory SQLite DB. The corresponding pytest fixtures are ``fake_event_bus``, ``test_app``, -``test_client``, and ``test_db_session``. See ``simple_module_testing.plugin`` +``test_client``, and ``test_db_session``. See ``simple_module_test.plugin`` for their definitions. """ -from simple_module_testing.app_factory import build_test_app -from simple_module_testing.fake_events import FakeEventBus, RecordedEvent -from simple_module_testing.session_cookie import forge_session_cookie +from simple_module_test.app_factory import build_test_app +from simple_module_test.fake_events import FakeEventBus, RecordedEvent +from simple_module_test.session_cookie import forge_session_cookie __all__ = [ "FakeEventBus", diff --git a/framework/testing/simple_module_testing/app_factory.py b/framework/testing/simple_module_test/app_factory.py similarity index 100% rename from framework/testing/simple_module_testing/app_factory.py rename to framework/testing/simple_module_test/app_factory.py diff --git a/framework/testing/simple_module_testing/fake_events.py b/framework/testing/simple_module_test/fake_events.py similarity index 100% rename from framework/testing/simple_module_testing/fake_events.py rename to framework/testing/simple_module_test/fake_events.py diff --git a/framework/testing/simple_module_testing/plugin.py b/framework/testing/simple_module_test/plugin.py similarity index 78% rename from framework/testing/simple_module_testing/plugin.py rename to framework/testing/simple_module_test/plugin.py index 94ec7d1b..8d53d563 100644 --- a/framework/testing/simple_module_testing/plugin.py +++ b/framework/testing/simple_module_test/plugin.py @@ -1,7 +1,7 @@ """Pytest plugin — registered via the ``pytest11`` entry_point in pyproject.toml. Fixtures declared here are available to every test run in any environment -that has ``simple_module_testing`` installed, without a ``conftest.py`` +that has ``simple_module_test`` installed, without a ``conftest.py`` import. Delete a fixture from this file and you break external modules' test suites — treat the fixture surface like a public API. """ @@ -10,8 +10,8 @@ import pytest -from simple_module_testing.app_factory import build_test_app as _build_test_app -from simple_module_testing.fake_events import FakeEventBus +from simple_module_test.app_factory import build_test_app as _build_test_app +from simple_module_test.fake_events import FakeEventBus @pytest.fixture diff --git a/framework/testing/simple_module_testing/session_cookie.py b/framework/testing/simple_module_test/session_cookie.py similarity index 100% rename from framework/testing/simple_module_testing/session_cookie.py rename to framework/testing/simple_module_test/session_cookie.py diff --git a/framework/testing/tests/test_app_factory.py b/framework/testing/tests/test_app_factory.py index fc1ba526..53e16f3e 100644 --- a/framework/testing/tests/test_app_factory.py +++ b/framework/testing/tests/test_app_factory.py @@ -32,21 +32,21 @@ async def ping() -> dict: class TestBuildTestApp: async def test_returns_fastapi_instance_from_class(self): """Passing a ModuleBase subclass instantiates it and returns a FastAPI app.""" - from simple_module_testing import build_test_app + from simple_module_test import build_test_app app = build_test_app(_EchoModule) assert isinstance(app, FastAPI) async def test_returns_fastapi_instance_from_instance(self): """Accepts an already-instantiated module too.""" - from simple_module_testing import build_test_app + from simple_module_test import build_test_app app = build_test_app(_EchoModule()) assert isinstance(app, FastAPI) async def test_registers_module_routes_with_prefix(self): """The module's register_routes() runs and its api routes appear under the prefix.""" - from simple_module_testing import build_test_app + from simple_module_test import build_test_app app = build_test_app(_EchoModule) paths = {getattr(r, "path", None) for r in app.routes} @@ -54,14 +54,14 @@ async def test_registers_module_routes_with_prefix(self): async def test_module_accessible_on_app_state(self): """The instance is stored on app.state.module so tests can poke at it.""" - from simple_module_testing import build_test_app + from simple_module_test import build_test_app app = build_test_app(_EchoModule) assert isinstance(app.state.module, _EchoModule) async def test_isolates_from_other_installed_modules(self): """build_test_app only mounts the given module — Products/Auth routes are absent.""" - from simple_module_testing import build_test_app + from simple_module_test import build_test_app app = build_test_app(_EchoModule) paths = {getattr(r, "path", None) for r in app.routes} diff --git a/framework/testing/tests/test_fake_events.py b/framework/testing/tests/test_fake_events.py index 505147fe..4102fa24 100644 --- a/framework/testing/tests/test_fake_events.py +++ b/framework/testing/tests/test_fake_events.py @@ -22,7 +22,7 @@ class OrderShipped(Event): class TestFakeEventBus: async def test_records_publish(self): """publish() records the event for later assertion.""" - from simple_module_testing import FakeEventBus + from simple_module_test import FakeEventBus bus = FakeEventBus() await bus.publish(OrderCreated(order_id=42)) @@ -33,7 +33,7 @@ async def test_records_publish(self): async def test_records_publish_nowait(self): """publish_nowait() also records without awaiting.""" - from simple_module_testing import FakeEventBus + from simple_module_test import FakeEventBus bus = FakeEventBus() bus.publish_nowait(OrderCreated(order_id=7)) @@ -41,7 +41,7 @@ async def test_records_publish_nowait(self): async def test_find_by_type(self): """find_by_type filters the recorded log to a single event class.""" - from simple_module_testing import FakeEventBus + from simple_module_test import FakeEventBus bus = FakeEventBus() await bus.publish(OrderCreated(order_id=1)) @@ -56,7 +56,7 @@ async def test_find_by_type(self): async def test_clear_resets_log(self): """clear() empties the recorded events so test phases can isolate state.""" - from simple_module_testing import FakeEventBus + from simple_module_test import FakeEventBus bus = FakeEventBus() await bus.publish(OrderCreated()) @@ -65,7 +65,7 @@ async def test_clear_resets_log(self): async def test_subscribed_handlers_still_fire(self): """FakeEventBus is a real EventBus — subscribers still run; recording is additive.""" - from simple_module_testing import FakeEventBus + from simple_module_test import FakeEventBus bus = FakeEventBus() received: list[int] = [] @@ -82,7 +82,7 @@ async def handler(event: OrderCreated) -> None: async def test_assert_published_raises_when_missing(self): """assert_published raises AssertionError when no matching event was recorded.""" - from simple_module_testing import FakeEventBus + from simple_module_test import FakeEventBus bus = FakeEventBus() await bus.publish(OrderCreated(order_id=1)) @@ -93,7 +93,7 @@ async def test_assert_published_raises_when_missing(self): async def test_assert_published_succeeds_when_present(self): """assert_published returns the matching events when at least one is found.""" - from simple_module_testing import FakeEventBus + from simple_module_test import FakeEventBus bus = FakeEventBus() await bus.publish(OrderCreated(order_id=1)) diff --git a/modules/background_tasks/tests/test_signals.py b/modules/background_tasks/tests/test_signals.py index 6f2c38a2..15972837 100644 --- a/modules/background_tasks/tests/test_signals.py +++ b/modules/background_tasks/tests/test_signals.py @@ -29,7 +29,7 @@ on_task_success, unbind_event_bus, ) -from simple_module_testing import FakeEventBus +from simple_module_test import FakeEventBus from sqlalchemy import select diff --git a/modules/users/tests/conftest.py b/modules/users/tests/conftest.py index 3b346583..733290a1 100644 --- a/modules/users/tests/conftest.py +++ b/modules/users/tests/conftest.py @@ -17,7 +17,7 @@ import httpx import pytest from simple_module_hosting.settings import Settings -from simple_module_testing import forge_session_cookie +from simple_module_test import forge_session_cookie from sqlalchemy.ext.asyncio import AsyncSession from users.constants import ADMIN_ROLE_ID, USER_ROLE_ID diff --git a/modules/users/tests/test_user_manager.py b/modules/users/tests/test_user_manager.py index 76521331..c4455cec 100644 --- a/modules/users/tests/test_user_manager.py +++ b/modules/users/tests/test_user_manager.py @@ -115,7 +115,7 @@ async def test_accepts_valid_password(self, manager, fake_user): class TestOnAfterRegister: @pytest.mark.anyio async def test_publishes_user_registered(self, manager, fake_user): - from simple_module_testing import FakeEventBus + from simple_module_test import FakeEventBus from users.contracts.events import UserRegistered bus = FakeEventBus() diff --git a/scripts/loadtest_seed.py b/scripts/loadtest_seed.py index 362efbb0..890859d3 100644 --- a/scripts/loadtest_seed.py +++ b/scripts/loadtest_seed.py @@ -17,7 +17,7 @@ from simple_module_db.session import init_db from simple_module_hosting.settings import Settings -from simple_module_testing import forge_session_cookie +from simple_module_test import forge_session_cookie from users.bootstrap import create_admin LOAD_EMAIL = "loadtest@example.com" diff --git a/tests/benchmarks/test_session_cookie_bench.py b/tests/benchmarks/test_session_cookie_bench.py index cf82aed3..9b6d8732 100644 --- a/tests/benchmarks/test_session_cookie_bench.py +++ b/tests/benchmarks/test_session_cookie_bench.py @@ -9,7 +9,7 @@ from __future__ import annotations import pytest -from simple_module_testing import forge_session_cookie +from simple_module_test import forge_session_cookie pytestmark = pytest.mark.perf diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 7f39f874..e50f136f 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -18,7 +18,7 @@ import httpx import pytest from fastapi_users.password import PasswordHelper -from simple_module_testing import forge_session_cookie +from simple_module_test import forge_session_cookie from sqlalchemy import select