Testing API#

To use the fixtures provided by this module, add the following line to your conftest.py:

pytest_plugins = ["fastapi_restly.pytest_fixtures"]

This imports all fixtures (app, client, session, async_session, etc.) into your test session without needing to import them individually.

class fastapi_restly.testing.RestlyTestClient(app: ASGIApp, base_url: str = 'http://testserver', raise_server_exceptions: bool = True, root_path: str = '', backend: Literal['asyncio', 'trio'] = 'asyncio', backend_options: dict[str, Any] | None = None, cookies: httpx._types.CookieTypes | None = None, headers: dict[str, str] | None = None, follow_redirects: bool = True, client: tuple[str, int] = ('testclient', 50000))#

Bases: TestClient

Custom TestClient that automatically checks response codes and provides clear error messages.

assert_status(response: Response, expected_code: int | None = None)#

Check if the response status code matches the expected code.

delete(url: str, *, assert_status_code: int | None = 204, **kwargs) Response#

Make a DELETE request. Asserts the response status code matches assert_status_code (default: 204). Pass assert_status_code=None to skip the assertion.

get(url: str, *, assert_status_code: int | None = 200, **kwargs) Response#

Make a GET request. Asserts the response status code matches assert_status_code (default: 200). Pass assert_status_code=None to skip the assertion.

patch(url: str, *, assert_status_code: int | None = 200, **kwargs) Response#

Make a PATCH request. Asserts the response status code matches assert_status_code (default: 200). Pass assert_status_code=None to skip the assertion.

post(url: str, *, assert_status_code: int | None = 201, **kwargs) Response#

Make a POST request. Asserts the response status code matches assert_status_code (default: 201). Pass assert_status_code=None to skip the assertion.

put(url: str, *, assert_status_code: int | None = 200, **kwargs) Response#

Make a PUT request. Asserts the response status code matches assert_status_code (default: 200). Pass assert_status_code=None to skip the assertion.

fastapi_restly.testing.app() FastAPI#

Create a FastAPI app instance for testing.

fastapi_restly.testing.async_session(_shared_connection) AsyncIterator[AsyncSession]#

Pytest fixture providing a database session with savepoint-based isolation.

Each test runs inside a savepoint. At the end of the test, the savepoint is rolled back, leaving the database clean for the next test.

NOTE: Calling session.rollback() inside a test rolls back to the last savepoint (created by each patched commit()), NOT to the start of the test. This differs from production behavior. To undo all changes in a test, use session.rollback() after each commit(), but be aware that data added before the last commit() is still visible.

fastapi_restly.testing.autouse_alembic_upgrade(project_root)#
fastapi_restly.testing.autouse_savepoint_only_mode_sessions() None#
fastapi_restly.testing.client(app) RestlyTestClient#

Create a RestlyTestClient instance for testing.

fastapi_restly.testing.project_root() Path#

Return the project root directory.

fastapi_restly.testing.session(_shared_connection) Iterator[Session]#

Pytest fixture providing a database session with savepoint-based isolation.

Each test runs inside a savepoint. At the end of the test, the savepoint is rolled back, leaving the database clean for the next test.

NOTE: Calling session.rollback() inside a test rolls back to the last savepoint (created by each patched commit()), NOT to the start of the test. This differs from production behavior. To undo all changes in a test, use session.rollback() after each commit(), but be aware that data added before the last commit() is still visible.