|
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