Skip to content
This repository has been archived by the owner on Sep 12, 2023. It is now read-only.

0.28 #245

Merged
merged 6 commits into from
Jan 16, 2023
Merged

0.28 #245

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
3 changes: 2 additions & 1 deletion .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ type-checking-exempt-modules = from sqlalchemy.orm
per-file-ignores =
examples/dto/*:T201,TC
examples/tests/*:SCS108,PT013
src/pytest_starlite_saqlalchemy/__init__.py:F401
src/starlite_saqlalchemy/dependencies.py:TC
src/starlite_saqlalchemy/health.py:TC
src/starlite_saqlalchemy/repository/filters.py:TC
src/starlite_saqlalchemy/scripts.py:T201
src/starlite_saqlalchemy/settings.py:TC
src/starlite_saqlalchemy/testing.py:SCS108
src/starlite_saqlalchemy/testing/controller_test.py:SCS108
src/starlite_saqlalchemy/users/controllers.py:TC
tests/*:SCS108,PT013
tests/integration/test_tests.py:TC002,SCS108
Expand Down
11 changes: 5 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ on:
push:
branches: [main]
pull_request:
branches: [main]

env:
FORCE_COLOR: "1"
Expand Down Expand Up @@ -35,7 +34,7 @@ jobs:
with:
python-version: ${{env.PYTHON_LATEST}}
- name: Install Dependencies
run: python -m pip install --upgrade wheel tox
run: python -m pip install --upgrade -r requirements.ci.txt
- run: python -m tox -e pylint
mypy:
name: mypy
Expand All @@ -56,7 +55,7 @@ jobs:
with:
python-version: ${{env.PYTHON_LATEST}}
- name: Install Dependencies
run: python -m pip install --upgrade wheel tox
run: python -m pip install --upgrade -r requirements.ci.txt
- run: python -m tox -e mypy
pyright:
name: pyright
Expand All @@ -78,7 +77,7 @@ jobs:
with:
python-version: ${{env.PYTHON_LATEST}}
- name: Install Dependencies
run: python -m pip install --upgrade wheel tox
run: python -m pip install --upgrade -r requirements.ci.txt
- run: python -m tox -e pyright
tests:
name: tests on ${{matrix.python-version}}
Expand Down Expand Up @@ -108,7 +107,7 @@ jobs:
with:
python-version: ${{matrix.python-version}}
- name: Install Dependencies
run: python -m pip install --upgrade wheel tox tox-gh-actions
run: python -m pip install --upgrade -r requirements.ci.txt tox-gh-actions
- run: python -m tox
- name: Upload Coverage Data
uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb # @v3.1.1
Expand All @@ -133,7 +132,7 @@ jobs:
- uses: actions/setup-python@5ccb29d8773c3f3f653e1705f474dfaa8a06a912 #v4.4.0
with:
python-version: ${{env.PYTHON_LATEST}}
- run: python -m pip install --upgrade wheel tox
- run: python -m pip install --upgrade -r requirements.ci.txt
- name: Download coverage data
uses: actions/download-artifact@9782bd6a9848b53b110e712e20e42d89988822b7 # @v3.0.1
with:
Expand Down
137 changes: 137 additions & 0 deletions docs/testing/pytest_plugin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# Pytest Plugin

The nature of applications built with the `starlite-saqlalchemy` pattern is that they rely heavily
on connected services.

Abstraction of [PostgreSQL][2] and [Redis][3] connectivity boilerplate is a nice convenience,
however to successfully patch the application for testing requires deeper knowledge of the
implementation than would be otherwise necessary.

So, `starlite-saqlalchemy` ships with a selection of [pytest fixtures][1] that are often necessary
when building applications such as these.

## `app`

The `app` fixture provides an instance of a `Starlite` application.

```python
from __future__ import annotations

from starlite import Starlite


def test_app_fixture(app: Starlite) -> None:
assert isinstance(app, Starlite)
```

The value of Pytest ini option, `test_app` is used to determine the application to load.

```toml
# pyproject.toml

[tool.pytest.ini_options]
test_app = "app.main:create_app"
```

If no value is configured for the `test_app` ini option, the default location of
`"app.main:create_app"` is searched.

The value of the `test_app` ini option can either point to an application factory or `Starlite`
instance.

If the object found at the import path is not a `Starlite` instance, the fixture assumes it is
an application factory, and will call the object and return the response.

The value of `test_app` is resolved using the uvicorn `import_from_string()` function, so it
supports the same format as `uvicorn` supports for its `app` and `factory` parameters.

## `client`

A `starlite.testing.TestClient` instance, wired to the same application that is produced by the
`app` fixture.

## `cap_logger`

The `cap_logger` fixture provides an instance of [`structlog.testing.CapturingLogger`][4].

```python
from __future__ import annotations

from typing import TYPE_CHECKING

from structlog.testing import CapturedCall

if TYPE_CHECKING:
from structlog.testing import CapturingLogger


def test_app_fixture(cap_logger: CapturingLogger) -> None:
cap_logger.info("hello")
cap_logger.info("hello", when="again")
assert cap_logger.calls == [
CapturedCall(method_name="info", args=("hello",), kwargs={}),
CapturedCall(method_name="info", args=("hello",), kwargs={"when": "again"}),
]
```

The `cap_logger` fixture will capture any `structlog` calls made by the starlite application or the
SAQ worker, so that they can be inspected as part of tests.

```python
from __future__ import annotations

from typing import TYPE_CHECKING

from httpx import AsyncClient

if TYPE_CHECKING:
from starlite import Starlite
from structlog.testing import CapturingLogger


async def test_health_logging_skipped(
app: Starlite, cap_logger: CapturingLogger
) -> None:
"""Test that calls to the health check route are not logged."""

async with AsyncClient(app=app, base_url="http://testserver") as client:
response = await client.get("/health")
assert response.status_code == 200

assert [] == cap_logger.calls
```

## is_unit_test

The `is_unit_test` fixture returns a `bool` that indicates if the test suite believes it is running
a unit test, or an integration test.

To determine this, we compare the path of the running test to the value of the Pytest ini option
`unit_test_pattern`, which by default is `"^.*/tests/unit/.*$"`.

This fixture is used to make fixtures behave differently between unit and integration test contexts.

## _patch_http_close

This is an [`autouse` fixture][5], that prevents HTTP clients that are defined in the global scope
from being closed.

The application is configured to close all instantiated HTTP clients on app shutdown, however when
apps are defined in a global/class scope, a test that runs after the first application shutdown in
the test suite would fail.

## _patch_sqlalchemy_plugin

This is an [`autouse` fixture][5], that mocks out the `on_shutdown` method of the SQLAlchemy config
object for unit tests.

## _patch_worker

This is an [`autouse` fixture][5], that mocks out the `on_app_startup` and `stop` methods of
`worker.Worker` type for unit tests.

[1]: https://docs.pytest.org/en/latest/explanation/fixtures.html#about-fixtures
[2]: https://www.postgresql.org/
[3]: https://redis.io
[4]: https://www.structlog.org/en/stable/api.html#structlog.testing.CapturingLogger
[5]: https://docs.pytest.org/en/6.2.x/fixture.html#autouse-fixtures-fixtures-you-don-t-have-to-request
2 changes: 2 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ nav:
- DTOs: dto.md
- Async Worker: async_worker.md
- Logging: logging.md
- Testing:
- Pytest Plugin: testing/pytest_plugin.md
- Reference: reference/
watch:
- src/starlite_saqlalchemy
Expand Down
Loading