From 03241530d9c7b96bb517e33b556b18d0e574dd8e Mon Sep 17 00:00:00 2001 From: saltie2193 Date: Sat, 12 Oct 2024 21:03:27 +0200 Subject: [PATCH 1/2] Improve backend test performance by patching password hashing * Patch password hashing during tests --- backend/app/tests/conftest.py | 18 ++++++++++++++++-- backend/app/tests/utils/utils.py | 23 +++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/backend/app/tests/conftest.py b/backend/app/tests/conftest.py index 90ab39a357..516e6e4e65 100644 --- a/backend/app/tests/conftest.py +++ b/backend/app/tests/conftest.py @@ -9,12 +9,26 @@ from app.main import app from app.models import Item, User from app.tests.utils.user import authentication_token_from_email -from app.tests.utils.utils import get_superuser_token_headers +from app.tests.utils.utils import get_superuser_token_headers, patch_password_hashing + + +@pytest.fixture(scope="session") +def disable_password_hashing() -> Generator[None, None, None]: + with patch_password_hashing("app.core.security"): + yield @pytest.fixture(scope="session", autouse=True) -def db() -> Generator[Session, None, None]: +def db( + disable_password_hashing: Generator[None, None, None], # noqa: ARG001 +) -> Generator[Session, None, None]: with Session(engine) as session: + # cleanup db to prevent interferences with tests + # all existing data will be deleted anyway after the tests run + session.execute(delete(User)) + session.execute(delete(Item)) + session.commit() + init_db(session) yield session statement = delete(Item) diff --git a/backend/app/tests/utils/utils.py b/backend/app/tests/utils/utils.py index 184bac44d9..8363cf590a 100644 --- a/backend/app/tests/utils/utils.py +++ b/backend/app/tests/utils/utils.py @@ -1,5 +1,8 @@ import random import string +from collections.abc import Generator +from contextlib import contextmanager +from unittest.mock import patch from fastapi.testclient import TestClient @@ -24,3 +27,23 @@ def get_superuser_token_headers(client: TestClient) -> dict[str, str]: a_token = tokens["access_token"] headers = {"Authorization": f"Bearer {a_token}"} return headers + + +@contextmanager +def patch_password_hashing(*modules: str) -> Generator[None, None, None]: + """ + Contextmanager to patch ``pwd_context`` in the given modules. + :param modules: list of modules to patch. + :return: + """ + patchers = [] + for module in modules: + patcher_p = patch(f"{module}.pwd_context.verify", lambda x, y: x == y) + patcher_h = patch(f"{module}.pwd_context.hash", lambda x: x) + patcher_p.start() + patcher_h.start() + + patchers.extend((patcher_p, patcher_h)) + yield + for patcher in patchers: + patcher.stop() From 5fe97127df85febb1aae07ffca74bc7c8ff16554 Mon Sep 17 00:00:00 2001 From: saltie2193 Date: Sat, 12 Oct 2024 21:03:40 +0200 Subject: [PATCH 2/2] Use `contextlib.ExitStack` for managing multiple patchers --- backend/app/tests/utils/utils.py | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/backend/app/tests/utils/utils.py b/backend/app/tests/utils/utils.py index 8363cf590a..c1ba93fd13 100644 --- a/backend/app/tests/utils/utils.py +++ b/backend/app/tests/utils/utils.py @@ -1,7 +1,7 @@ import random import string from collections.abc import Generator -from contextlib import contextmanager +from contextlib import ExitStack, contextmanager from unittest.mock import patch from fastapi.testclient import TestClient @@ -36,14 +36,10 @@ def patch_password_hashing(*modules: str) -> Generator[None, None, None]: :param modules: list of modules to patch. :return: """ - patchers = [] - for module in modules: - patcher_p = patch(f"{module}.pwd_context.verify", lambda x, y: x == y) - patcher_h = patch(f"{module}.pwd_context.hash", lambda x: x) - patcher_p.start() - patcher_h.start() - - patchers.extend((patcher_p, patcher_h)) - yield - for patcher in patchers: - patcher.stop() + with ExitStack() as stack: + for module in modules: + stack.enter_context( + patch(f"{module}.pwd_context.verify", lambda x, y: x == y) + ) + stack.enter_context(patch(f"{module}.pwd_context.hash", lambda x: x)) + yield