Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions docs/module-authoring.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,15 +256,15 @@ 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
[project.optional-dependencies]
dev = [
"pytest>=8.0",
"pytest-asyncio>=0.24",
"simple_module_testing>=0.1,<1.0",
"simple_module_test>=0.1,<1.0",
]
```

Expand Down
4 changes: 2 additions & 2 deletions docs/release.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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/) |
Expand Down
2 changes: 1 addition & 1 deletion framework/hosting/simple_module_hosting/app_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -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])
Expand Down
2 changes: 1 addition & 1 deletion framework/hosting/simple_module_hosting/scaffolding.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
"""

Expand Down
4 changes: 2 additions & 2 deletions framework/testing/README.md
Original file line number Diff line number Diff line change
@@ -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.

Expand All @@ -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]"
```
Expand Down
6 changes: 3 additions & 3 deletions framework/testing/pyproject.toml
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -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"
Expand All @@ -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 }
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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",
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
"""
Expand All @@ -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
Expand Down
10 changes: 5 additions & 5 deletions framework/testing/tests/test_app_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,36 +32,36 @@ 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}
assert "/api/echo/ping" in paths

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}
Expand Down
14 changes: 7 additions & 7 deletions framework/testing/tests/test_fake_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -33,15 +33,15 @@ 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))
assert len(bus.events) == 1

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))
Expand All @@ -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())
Expand All @@ -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] = []
Expand All @@ -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))
Expand All @@ -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))
Expand Down
2 changes: 1 addition & 1 deletion modules/background_tasks/tests/test_signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down
2 changes: 1 addition & 1 deletion modules/users/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion modules/users/tests/test_user_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion scripts/loadtest_seed.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion tests/benchmarks/test_session_cookie_bench.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion tests/integration/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down
Loading