|
1 | 1 | from collections.abc import Generator |
| 2 | +from contextlib import nullcontext |
2 | 3 |
|
3 | 4 | import pytest |
| 5 | +from _pytest.fixtures import FixtureRequest |
4 | 6 | from fastapi.testclient import TestClient |
5 | 7 | from sqlmodel import Session, delete |
6 | 8 |
|
|
12 | 14 | from app.tests.utils.utils import get_superuser_token_headers, patch_password_hashing |
13 | 15 |
|
14 | 16 |
|
15 | | -@pytest.fixture(scope="session") |
16 | | -def disable_password_hashing() -> Generator[None, None, None]: |
17 | | - with patch_password_hashing("app.core.security"): |
| 17 | +@pytest.fixture(scope="module", autouse=True) |
| 18 | +def disable_password_hashing(request: FixtureRequest) -> Generator[None, None, None]: |
| 19 | + """Fixture disabling password hashing |
| 20 | +
|
| 21 | + Password hashing can be enabled on module level by marking the module with `pytest.mark.enable_password_hashing`. |
| 22 | + """ |
| 23 | + |
| 24 | + with ( |
| 25 | + patch_password_hashing("app.core.security") |
| 26 | + if all(m.name != "enable_password_hashing" for m in request.node.iter_markers()) |
| 27 | + else nullcontext() |
| 28 | + ): |
18 | 29 | yield |
19 | 30 |
|
20 | 31 |
|
21 | | -@pytest.fixture(scope="session", autouse=True) |
22 | | -def db( |
23 | | - disable_password_hashing: Generator[None, None, None], # noqa: ARG001 |
24 | | -) -> Generator[Session, None, None]: |
| 32 | +@pytest.fixture(scope="session") |
| 33 | +def db() -> Generator[Session, None, None]: |
| 34 | + """ |
| 35 | + Module scoped fixture providing a database session initialized with `init_db`. |
| 36 | + """ |
25 | 37 | with Session(engine) as session: |
26 | | - # cleanup db to prevent interferences with tests |
27 | | - # all existing data will be deleted anyway after the tests run |
28 | | - session.execute(delete(User)) |
| 38 | + yield session |
| 39 | + # Cleanup test database |
29 | 40 | session.execute(delete(Item)) |
| 41 | + session.execute(delete(User)) |
30 | 42 | session.commit() |
31 | 43 |
|
32 | | - init_db(session) |
33 | | - yield session |
34 | | - statement = delete(Item) |
35 | | - session.execute(statement) |
36 | | - statement = delete(User) |
37 | | - session.execute(statement) |
38 | | - session.commit() |
| 44 | + |
| 45 | +@pytest.fixture(scope="module", autouse=True) |
| 46 | +def init_db_fixture(db: Session) -> None: |
| 47 | + # note: deleting all users here is required to enable or disable password hashing per test module. |
| 48 | + # If we don't delete all users here, the users created during `init_db` will not be re-created and the password will stay (un)hashed, |
| 49 | + # leading to possibly failing tests relying on the created user for authentication. |
| 50 | + db.execute(delete(Item)) |
| 51 | + db.execute(delete(User)) |
| 52 | + init_db(db) |
| 53 | + db.commit() |
39 | 54 |
|
40 | 55 |
|
41 | 56 | @pytest.fixture(scope="module") |
42 | | -def client() -> Generator[TestClient, None, None]: |
| 57 | +def client(db: Session) -> Generator[TestClient, None, None]: # noqa: ARG001 |
| 58 | + """ |
| 59 | + Module scoped fixture providing a `TestClient` instance. |
| 60 | +
|
| 61 | + NOTE: This fixture uses the `db` fixture WITHOUT hashing passwords! |
| 62 | + """ |
43 | 63 | with TestClient(app) as c: |
44 | 64 | yield c |
45 | 65 |
|
|
0 commit comments