From f85af90b22ccb8db0c162eb12daec889a66a2e57 Mon Sep 17 00:00:00 2001 From: NamazovMaksim Date: Mon, 18 May 2026 21:20:06 +0300 Subject: [PATCH 01/10] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D1=84=D0=B8=D0=BA=D1=81=D1=82=D1=83=D1=80?= =?UTF-8?q?=D1=8B:=20logging=5Fsql=5Freq=5Fbefore=5Fexecute=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BB=D0=BE=D0=B3=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=BF=D0=BE=D0=B4=D0=B3=D0=BE=D1=82=D0=BE=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=BD=D1=8B=D1=85=20SQL-=D0=B7=D0=B0=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D1=81=D0=BE=D0=B2=20=D0=B8=20override=5Fdbsession?= =?UTF-8?q?=5Fin=5Froute,=20=D0=BC=D0=BE=D0=BA=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B5=D0=BE=D0=BF=D1=80=D0=B5=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=81=D0=B5=D1=81=D1=81=D0=B8?= =?UTF-8?q?=D0=B8=20=D1=80=D1=83=D1=87=D0=BA=D0=B8=20=D0=BD=D0=B0=20=D1=82?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D0=BE=D0=B2=D1=83=D1=8E=20=D1=81=D0=B5=D1=81?= =?UTF-8?q?=D1=81=D0=B8=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/conftest.py | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 029db70..8831f7e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -10,6 +10,8 @@ from alembic.config import Config as AlembicConfig from fastapi.testclient import TestClient from sqlalchemy import create_engine +from sqlalchemy import event +from fastapi_sqlalchemy import db from sqlalchemy.orm import sessionmaker from testcontainers.postgres import PostgresContainer @@ -91,6 +93,28 @@ def dbsession(db_container): yield session +@pytest.fixture() +def logging_sql_req_before_execute(dbsession): + """ + Фикстура для логирования всех сформированных в рамках одной транзакции + SQL-запросов, до их отправки в бд, то есть до Session.flush() или + до Session.commit(). + """ + engine = dbsession.get_bind() + @event.listens_for(engine, "before_execute", named=True) + def sql_requests_listener(**kw_entities_of_executing): + print("\n========= SQL command =========\n") + print(f"SQL was sended: {kw_entities_of_executing.get("clauseelement")}\n") + print("===============================\n") + + + +@pytest.fixture() +def override_dbsession_in_route(dbsession, mocker): + "Мок для подмены db.session в ручке на тестовую сессию dbsession" + mocker.patch.object(db.__class__, "session", property(lambda self: dbsession)) + + @pytest.fixture def client(mocker): user_mock = mocker.patch('auth_lib.fastapi.UnionAuth.__call__') @@ -214,11 +238,9 @@ def lecturers(dbsession): Lecturer(id=4, first_name='test_fname3', last_name='test_lname3', middle_name='test_mname3', timetable_id=9903) ) lecturers[-1].is_deleted = True - for lecturer in lecturers: - dbsession.add(lecturer) + dbsession.add_all(lecturers) dbsession.commit() yield lecturers - for lecturer in lecturers: for row in lecturer.comments: dbsession.delete(row) From 9ee40011083dca5146aa11fdda548cc7492d1ffa Mon Sep 17 00:00:00 2001 From: NamazovMaksim Date: Mon, 18 May 2026 21:25:43 +0300 Subject: [PATCH 02/10] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20relationship=20=D0=B4=D0=BB=D1=8F=20=D1=82?= =?UTF-8?q?=D0=B0=D0=B1=D0=BB=D0=B8=D1=86=20Lectorer=20=D0=B8=20LectorerUs?= =?UTF-8?q?erComment=20=D1=81=20=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE=D0=B9?= =?UTF-8?q?=D0=BA=D0=BE=D0=B9=20cascade,=20=D1=87=D1=82=D0=BE=20=D0=B4?= =?UTF-8?q?=D0=B0=D1=82=D1=8C=20=D0=B0=D0=BB=D1=85=D0=B8=D0=BC=D0=B8=D0=B8?= =?UTF-8?q?=20=D0=BF=D0=BE=D0=BD=D1=8F=D1=82=D1=8C=20=D0=B2=20=D0=BA=D0=B0?= =?UTF-8?q?=D0=BA=D0=BE=D0=BC=20=D0=BF=D0=BE=D1=80=D1=8F=D0=B4=D0=BA=D0=B5?= =?UTF-8?q?=20=D0=B8=D1=85=20=D1=83=D0=B4=D0=B0=D0=BB=D1=8F=D1=82=D1=8C,?= =?UTF-8?q?=20=D0=B2=D0=BD=D0=B5=20=D0=B7=D0=B0=D0=B2=D0=B8=D1=81=D0=B8?= =?UTF-8?q?=D0=BC=D0=BE=D1=81=D1=82=D0=B8=20=D0=BE=D1=82=20=D1=81=D0=B2?= =?UTF-8?q?=D1=8F=D0=B7=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D0=B4=D1=80=D1=83?= =?UTF-8?q?=D0=B3=D0=B8=D1=85=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8=D1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rating_api/models/db.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rating_api/models/db.py b/rating_api/models/db.py index 1cdc664..120e70f 100644 --- a/rating_api/models/db.py +++ b/rating_api/models/db.py @@ -50,6 +50,7 @@ class Lecturer(BaseDbModel): avatar_link: Mapped[str] = mapped_column(String, nullable=True, comment="Ссылка на аву препода") timetable_id: Mapped[int] comments: Mapped[list[Comment]] = relationship("Comment", back_populates="lecturer") + lecturer_user_comments: Mapped[list[LecturerUserComment]] = relationship("LecturerUserComment", back_populates="lecturer_comments", cascade="all, delete-orphan") mark_weighted: Mapped[float] = mapped_column( Float, nullable=False, @@ -288,6 +289,7 @@ class LecturerUserComment(BaseDbModel): id: Mapped[int] = mapped_column(Integer, primary_key=True) user_id: Mapped[int] = mapped_column(Integer, nullable=False) lecturer_id: Mapped[int] = mapped_column(Integer, ForeignKey("lecturer.id")) + lecturer_comments: Mapped[Lecturer] = relationship("Lecturer", back_populates="lecturer_user_comments") create_ts: Mapped[datetime.datetime] = mapped_column( DateTime, default=datetime.datetime.now(datetime.timezone.utc), nullable=False ) From 47b118c6db6f2489a5f7ea1308b1ef007fd136a3 Mon Sep 17 00:00:00 2001 From: NamazovMaksim Date: Mon, 18 May 2026 21:28:12 +0300 Subject: [PATCH 03/10] =?UTF-8?q?=D0=92=20.gitignore=20=D0=B4=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=BE=20=D0=B8=D1=81=D0=BA=D0=BB?= =?UTF-8?q?=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=84=D0=B0=D0=B9=D0=BB?= =?UTF-8?q?=D0=B0=20uv.lock=20=D0=B4=D0=BB=D1=8F=20=D0=BF=D0=B0=D0=BA?= =?UTF-8?q?=D0=B5=D1=82=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=BC=D0=B5=D0=BD=D0=B5?= =?UTF-8?q?=D0=B4=D0=B6=D0=B5=D1=80=D0=B0=20uv?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index b6e4761..b85d216 100644 --- a/.gitignore +++ b/.gitignore @@ -127,3 +127,6 @@ dmypy.json # Pyre type checker .pyre/ + +# uv pocket manager +uv.lock From 54ccba8397c14e74ea0753572f2d7dc4fd811f82 Mon Sep 17 00:00:00 2001 From: NamazovMaksim Date: Tue, 19 May 2026 00:46:07 +0300 Subject: [PATCH 04/10] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20=D0=BC=D0=BE=D0=BA=20=D0=BF=D0=BE=D0=BB=D1=8C?= =?UTF-8?q?=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D0=B5=D0=BB=D1=8F=20=D1=81=20use?= =?UTF-8?q?rdata?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/conftest.py | 54 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 8831f7e..07603ef 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -10,8 +10,10 @@ from alembic.config import Config as AlembicConfig from fastapi.testclient import TestClient from sqlalchemy import create_engine + from sqlalchemy import event from fastapi_sqlalchemy import db + from sqlalchemy.orm import sessionmaker from testcontainers.postgres import PostgresContainer @@ -19,6 +21,7 @@ from rating_api.routes import app from rating_api.settings import Settings, get_settings +from auth_lib.fastapi import UnionAuth class PostgresConfig: """Дата-класс со значениями для контейнера с тестовой БД и alembic-миграции.""" @@ -116,16 +119,47 @@ def override_dbsession_in_route(dbsession, mocker): @pytest.fixture -def client(mocker): - user_mock = mocker.patch('auth_lib.fastapi.UnionAuth.__call__') - user_mock.return_value = { - "session_scopes": [{"id": 0, "name": "string", "comment": "string"}], - "user_scopes": [{"id": 0, "name": "string", "comment": "string"}], - "indirect_groups": [{"id": 0, "name": "string", "parent_id": 0}], - "groups": [{"id": 0, "name": "string", "parent_id": 0}], - "id": 0, - "email": "string", - } +def authlib_user(): + """Данные о пользователе, возвращаемые сервисом auth. + """ + return {"auth_methods":["email","github_auth"], + "session_scopes":[ + {"id":145,"name":"auth.session.create"}, + {"id":146,"name":"auth.session.update"}, + {"id":165,"name":"auth.user.selfdelete"} + ], + "user_scopes":[ + {"id":145,"name":"auth.session.create"}, + {"id":146,"name":"auth.session.update"}, + {"id":165,"name":"auth.user.selfdelete"} + ], + "indirect_groups":[99], + "groups":[99], + "id":0, + "email":"aslimbo2001@gmail.com", + "userdata":[ + {"category":"Личная информация","param":"Полное имя","value":"Namazov Maksim"}, + {"category":"Личная информация","param":"Фото","value":"https://avatars.githubusercontent.com/u/192724282?v=4"}, + {"category":"Контакты","param":"Имя пользователя GitHub","value":"CaseAsLimbo"} + ] + } + + + +@pytest.fixture() +def authlib_mock(mocker): + auth_mock = mocker.patch("auth_lib.fastapi.UnionAuth.__call__") + return auth_mock + + +@pytest.fixture() +def user_mock(authlib_mock, authlib_user): + auth_mock = authlib_mock.return_value = authlib_user + return auth_mock + + +@pytest.fixture +def client(mocker, user_mock): client = TestClient(app) return client From 944ae37b2f46012f7ff7a7ae5b88b5088ae43884 Mon Sep 17 00:00:00 2001 From: NamazovMaksim Date: Tue, 19 May 2026 17:07:11 +0300 Subject: [PATCH 05/10] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BD=D0=B0=D0=B7=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=B0=D1=82=D1=80=D0=B8=D0=B1=D1=83=D1=82=D0=B0=20lecturer=5Fc?= =?UTF-8?q?omments=20=D0=BD=D0=B0=20lecturer=20=D0=B2=20=D1=82=D0=B0=D0=B1?= =?UTF-8?q?=D0=BB=D0=B8=D1=86=D0=B5=20LecturerUserComments?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rating_api/models/db.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rating_api/models/db.py b/rating_api/models/db.py index 120e70f..31af7ec 100644 --- a/rating_api/models/db.py +++ b/rating_api/models/db.py @@ -50,7 +50,7 @@ class Lecturer(BaseDbModel): avatar_link: Mapped[str] = mapped_column(String, nullable=True, comment="Ссылка на аву препода") timetable_id: Mapped[int] comments: Mapped[list[Comment]] = relationship("Comment", back_populates="lecturer") - lecturer_user_comments: Mapped[list[LecturerUserComment]] = relationship("LecturerUserComment", back_populates="lecturer_comments", cascade="all, delete-orphan") + lecturer_user_comments: Mapped[list[LecturerUserComment]] = relationship("LecturerUserComment", back_populates="lecturer", cascade="all, delete-orphan") mark_weighted: Mapped[float] = mapped_column( Float, nullable=False, @@ -289,7 +289,7 @@ class LecturerUserComment(BaseDbModel): id: Mapped[int] = mapped_column(Integer, primary_key=True) user_id: Mapped[int] = mapped_column(Integer, nullable=False) lecturer_id: Mapped[int] = mapped_column(Integer, ForeignKey("lecturer.id")) - lecturer_comments: Mapped[Lecturer] = relationship("Lecturer", back_populates="lecturer_user_comments") + lecturer: Mapped[Lecturer] = relationship("Lecturer", back_populates="lecturer_user_comments") create_ts: Mapped[datetime.datetime] = mapped_column( DateTime, default=datetime.datetime.now(datetime.timezone.utc), nullable=False ) From b00ad8bef665900028f6f033ded706b2b660945b Mon Sep 17 00:00:00 2001 From: NamazovMaksim Date: Tue, 19 May 2026 21:08:54 +0300 Subject: [PATCH 06/10] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=BA=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82=D0=BD=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D0=B8=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B4=D0=B0=D0=BD?= =?UTF-8?q?=D0=BD=D1=8B=D1=85=20=D0=B2=20userdata=20=D0=BF=D0=B0=D1=80?= =?UTF-8?q?=D0=B0=D0=BC=D0=B5=D1=82=D1=80=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/conftest.py | 11 +++++++---- tests/test_routes/test_comment.py | 9 +++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 07603ef..f4b4e8a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -114,13 +114,16 @@ def sql_requests_listener(**kw_entities_of_executing): @pytest.fixture() def override_dbsession_in_route(dbsession, mocker): - "Мок для подмены db.session в ручке на тестовую сессию dbsession" + """ + Мок для подмены db.session в ручке на тестовую сессию dbsession + """ mocker.patch.object(db.__class__, "session", property(lambda self: dbsession)) @pytest.fixture def authlib_user(): - """Данные о пользователе, возвращаемые сервисом auth. + """ + Данные о пользователе, возвращаемые сервисом auth. """ return {"auth_methods":["email","github_auth"], "session_scopes":[ @@ -154,8 +157,8 @@ def authlib_mock(mocker): @pytest.fixture() def user_mock(authlib_mock, authlib_user): - auth_mock = authlib_mock.return_value = authlib_user - return auth_mock + authlib_mock.return_value = authlib_user + return authlib_mock @pytest.fixture diff --git a/tests/test_routes/test_comment.py b/tests/test_routes/test_comment.py index 0ea2692..6776096 100644 --- a/tests/test_routes/test_comment.py +++ b/tests/test_routes/test_comment.py @@ -7,6 +7,7 @@ from rating_api.models import Comment, CommentReaction, LecturerUserComment, Reaction, ReviewStatus from rating_api.settings import get_settings +from auth_lib.fastapi import UnionAuth logger = logging.getLogger(__name__) url: str = '/comment' @@ -177,6 +178,14 @@ def test_create_comment(client, dbsession, lecturers, body, lecturer_n, response_status): params = {"lecturer_id": lecturers[lecturer_n].id} post_response = client.post(url, json=body, params=params) + + # Проверка корректности переданных в userdata "param" + user = UnionAuth.__call__(post_response) + acceptable_params = ["Полное имя", "Фото", "Имя пользователя GitHub", "Номер Телефона"] + real_params = [i["param"] for i in user.get("userdata")] + for i in real_params: + assert i in acceptable_params, f"Не допустимый параметр: \"{i}\"! Список допустимых параметров: {acceptable_params}" + assert post_response.status_code == response_status if response_status == status.HTTP_200_OK: comment = Comment.query(session=dbsession).filter(Comment.uuid == post_response.json()["uuid"]).one_or_none() From e5d6cf19ed34689e91eb8f64a0e368126be20444 Mon Sep 17 00:00:00 2001 From: NamazovMaksim Date: Tue, 19 May 2026 21:30:12 +0300 Subject: [PATCH 07/10] =?UTF-8?q?=D0=91=D1=8B=D0=BB=D0=B8=20=D0=B4=D0=BE?= =?UTF-8?q?=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=B4=D0=BE=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D1=81=D0=BB=D1=83=D1=88=D0=B0=D1=82=D0=B5=D0=BB=D0=B8?= =?UTF-8?q?=20=D1=81=D0=BE=D0=B1=D1=8B=D1=82=D0=B8=D0=B9=20BEGIN,=20COMMIT?= =?UTF-8?q?=20=D0=B8=20ROLLBACK=20=D0=B2=20=D1=84=D0=B8=D0=BA=D1=81=D1=82?= =?UTF-8?q?=D1=83=D1=80=D1=83=20logging=5Fsql=5Freq=5Fbefore=5Fexecute?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/conftest.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index f4b4e8a..523b6ea 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -101,14 +101,33 @@ def logging_sql_req_before_execute(dbsession): """ Фикстура для логирования всех сформированных в рамках одной транзакции SQL-запросов, до их отправки в бд, то есть до Session.flush() или - до Session.commit(). + до Session.commit(), а так же событий сессии BEGIN, COMMIT и ROLLBACK """ engine = dbsession.get_bind() + @event.listens_for(engine, "before_execute", named=True) def sql_requests_listener(**kw_entities_of_executing): print("\n========= SQL command =========\n") print(f"SQL was sended: {kw_entities_of_executing.get("clauseelement")}\n") print("===============================\n") + + @event.listens_for(dbsession, "after_begin", named=True) + def begin_listener(**kw): + print("\n========= BEGIN =========\n") + print(f"BEGIN was executed\n") + print("===============================\n") + + @event.listens_for(dbsession, "after_rollback", named=True) + def begin_listener(**kw): + print("\n========= ROLLBACK =========\n") + print(f"ROLLBACK was executed\n") + print("===============================\n") + + @event.listens_for(dbsession, "after_commit", named=True) + def begin_listener(**kw): + print("\n========= COMMIT =========\n") + print(f"COMMIT was executed\n") + print("===============================\n") From 810eeb4bcfb6a9a7386bd38a18bd3c403b5249f3 Mon Sep 17 00:00:00 2001 From: NamazovMaksim Date: Tue, 19 May 2026 21:45:55 +0300 Subject: [PATCH 08/10] =?UTF-8?q?=D0=91=D1=8B=D0=BB=D0=B8=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D1=8B=20black=20=D0=B8=20i?= =?UTF-8?q?sort=20T=5FT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rating_api/models/db.py | 4 +- tests/conftest.py | 65 +++++++++++++++---------------- tests/test_routes/test_comment.py | 8 ++-- 3 files changed, 40 insertions(+), 37 deletions(-) diff --git a/rating_api/models/db.py b/rating_api/models/db.py index 31af7ec..5c75575 100644 --- a/rating_api/models/db.py +++ b/rating_api/models/db.py @@ -50,7 +50,9 @@ class Lecturer(BaseDbModel): avatar_link: Mapped[str] = mapped_column(String, nullable=True, comment="Ссылка на аву препода") timetable_id: Mapped[int] comments: Mapped[list[Comment]] = relationship("Comment", back_populates="lecturer") - lecturer_user_comments: Mapped[list[LecturerUserComment]] = relationship("LecturerUserComment", back_populates="lecturer", cascade="all, delete-orphan") + lecturer_user_comments: Mapped[list[LecturerUserComment]] = relationship( + "LecturerUserComment", back_populates="lecturer", cascade="all, delete-orphan" + ) mark_weighted: Mapped[float] = mapped_column( Float, nullable=False, diff --git a/tests/conftest.py b/tests/conftest.py index 523b6ea..f94524a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -9,11 +9,8 @@ from alembic import command from alembic.config import Config as AlembicConfig from fastapi.testclient import TestClient -from sqlalchemy import create_engine - -from sqlalchemy import event from fastapi_sqlalchemy import db - +from sqlalchemy import create_engine, event from sqlalchemy.orm import sessionmaker from testcontainers.postgres import PostgresContainer @@ -21,7 +18,6 @@ from rating_api.routes import app from rating_api.settings import Settings, get_settings -from auth_lib.fastapi import UnionAuth class PostgresConfig: """Дата-класс со значениями для контейнера с тестовой БД и alembic-миграции.""" @@ -100,7 +96,7 @@ def dbsession(db_container): def logging_sql_req_before_execute(dbsession): """ Фикстура для логирования всех сформированных в рамках одной транзакции - SQL-запросов, до их отправки в бд, то есть до Session.flush() или + SQL-запросов, до их отправки в бд, то есть до Session.flush() или до Session.commit(), а так же событий сессии BEGIN, COMMIT и ROLLBACK """ engine = dbsession.get_bind() @@ -108,27 +104,26 @@ def logging_sql_req_before_execute(dbsession): @event.listens_for(engine, "before_execute", named=True) def sql_requests_listener(**kw_entities_of_executing): print("\n========= SQL command =========\n") - print(f"SQL was sended: {kw_entities_of_executing.get("clauseelement")}\n") + print(f"SQL was sended: {kw_entities_of_executing.get('clauseelement')}\n") print("===============================\n") @event.listens_for(dbsession, "after_begin", named=True) def begin_listener(**kw): print("\n========= BEGIN =========\n") print(f"BEGIN was executed\n") - print("===============================\n") + print("===============================\n") @event.listens_for(dbsession, "after_rollback", named=True) def begin_listener(**kw): print("\n========= ROLLBACK =========\n") print(f"ROLLBACK was executed\n") - print("===============================\n") + print("===============================\n") @event.listens_for(dbsession, "after_commit", named=True) def begin_listener(**kw): print("\n========= COMMIT =========\n") print(f"COMMIT was executed\n") - print("===============================\n") - + print("===============================\n") @pytest.fixture() @@ -144,28 +139,32 @@ def authlib_user(): """ Данные о пользователе, возвращаемые сервисом auth. """ - return {"auth_methods":["email","github_auth"], - "session_scopes":[ - {"id":145,"name":"auth.session.create"}, - {"id":146,"name":"auth.session.update"}, - {"id":165,"name":"auth.user.selfdelete"} - ], - "user_scopes":[ - {"id":145,"name":"auth.session.create"}, - {"id":146,"name":"auth.session.update"}, - {"id":165,"name":"auth.user.selfdelete"} - ], - "indirect_groups":[99], - "groups":[99], - "id":0, - "email":"aslimbo2001@gmail.com", - "userdata":[ - {"category":"Личная информация","param":"Полное имя","value":"Namazov Maksim"}, - {"category":"Личная информация","param":"Фото","value":"https://avatars.githubusercontent.com/u/192724282?v=4"}, - {"category":"Контакты","param":"Имя пользователя GitHub","value":"CaseAsLimbo"} - ] - } - + return { + "auth_methods": ["email", "github_auth"], + "session_scopes": [ + {"id": 145, "name": "auth.session.create"}, + {"id": 146, "name": "auth.session.update"}, + {"id": 165, "name": "auth.user.selfdelete"}, + ], + "user_scopes": [ + {"id": 145, "name": "auth.session.create"}, + {"id": 146, "name": "auth.session.update"}, + {"id": 165, "name": "auth.user.selfdelete"}, + ], + "indirect_groups": [99], + "groups": [99], + "id": 0, + "email": "aslimbo2001@gmail.com", + "userdata": [ + {"category": "Личная информация", "param": "Полное имя", "value": "Namazov Maksim"}, + { + "category": "Личная информация", + "param": "Фото", + "value": "https://avatars.githubusercontent.com/u/192724282?v=4", + }, + {"category": "Контакты", "param": "Имя пользователя GitHub", "value": "CaseAsLimbo"}, + ], + } @pytest.fixture() diff --git a/tests/test_routes/test_comment.py b/tests/test_routes/test_comment.py index 6776096..38ae9e8 100644 --- a/tests/test_routes/test_comment.py +++ b/tests/test_routes/test_comment.py @@ -2,12 +2,12 @@ import logging import pytest +from auth_lib.fastapi import UnionAuth from starlette import status from rating_api.models import Comment, CommentReaction, LecturerUserComment, Reaction, ReviewStatus from rating_api.settings import get_settings -from auth_lib.fastapi import UnionAuth logger = logging.getLogger(__name__) url: str = '/comment' @@ -178,13 +178,15 @@ def test_create_comment(client, dbsession, lecturers, body, lecturer_n, response_status): params = {"lecturer_id": lecturers[lecturer_n].id} post_response = client.post(url, json=body, params=params) - + # Проверка корректности переданных в userdata "param" user = UnionAuth.__call__(post_response) acceptable_params = ["Полное имя", "Фото", "Имя пользователя GitHub", "Номер Телефона"] real_params = [i["param"] for i in user.get("userdata")] for i in real_params: - assert i in acceptable_params, f"Не допустимый параметр: \"{i}\"! Список допустимых параметров: {acceptable_params}" + assert ( + i in acceptable_params + ), f"Не допустимый параметр: \"{i}\"! Список допустимых параметров: {acceptable_params}" assert post_response.status_code == response_status if response_status == status.HTTP_200_OK: From a118c238150fd7df198782248bdaa1ca314f4373 Mon Sep 17 00:00:00 2001 From: NamazovMaksim Date: Tue, 19 May 2026 23:12:13 +0300 Subject: [PATCH 09/10] =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D0=B8=D0=BB=20?= =?UTF-8?q?=D0=BB=D0=B8=D1=87=D0=BD=D1=83=D1=8E=20=D0=B8=D0=BD=D1=84=D0=BE?= =?UTF-8?q?=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/conftest.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index f94524a..41f4ae0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -156,13 +156,7 @@ def authlib_user(): "id": 0, "email": "aslimbo2001@gmail.com", "userdata": [ - {"category": "Личная информация", "param": "Полное имя", "value": "Namazov Maksim"}, - { - "category": "Личная информация", - "param": "Фото", - "value": "https://avatars.githubusercontent.com/u/192724282?v=4", - }, - {"category": "Контакты", "param": "Имя пользователя GitHub", "value": "CaseAsLimbo"}, + {"category": "Личная информация", "param": "Полное имя", "value": "Тестовый Тест"}, ], } From 03429654fc6b8436a055f5fb2be1cc1c3960f816 Mon Sep 17 00:00:00 2001 From: NamazovMaksim Date: Wed, 20 May 2026 00:27:51 +0300 Subject: [PATCH 10/10] =?UTF-8?q?=D0=B1=D1=8B=D0=BB=D0=B8=20=D1=83=D0=B4?= =?UTF-8?q?=D0=B0=D0=BB=D0=B5=D0=BD=D1=8B=20=D1=84=D0=B8=D0=BA=D1=81=D1=82?= =?UTF-8?q?=D1=80=D1=8B=20=D0=B4=D0=BB=D1=8F=20=D0=BB=D0=BE=D0=B3=D0=B8?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20=D0=B8=20=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D0=B5=D0=BE=D0=BF=D1=80=D0=B5=D0=B4=D0=B5=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20dbsession?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/conftest.py | 45 +------------------------------ tests/test_routes/test_comment.py | 4 +-- 2 files changed, 3 insertions(+), 46 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 41f4ae0..561c6e8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -9,8 +9,7 @@ from alembic import command from alembic.config import Config as AlembicConfig from fastapi.testclient import TestClient -from fastapi_sqlalchemy import db -from sqlalchemy import create_engine, event +from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from testcontainers.postgres import PostgresContainer @@ -92,48 +91,6 @@ def dbsession(db_container): yield session -@pytest.fixture() -def logging_sql_req_before_execute(dbsession): - """ - Фикстура для логирования всех сформированных в рамках одной транзакции - SQL-запросов, до их отправки в бд, то есть до Session.flush() или - до Session.commit(), а так же событий сессии BEGIN, COMMIT и ROLLBACK - """ - engine = dbsession.get_bind() - - @event.listens_for(engine, "before_execute", named=True) - def sql_requests_listener(**kw_entities_of_executing): - print("\n========= SQL command =========\n") - print(f"SQL was sended: {kw_entities_of_executing.get('clauseelement')}\n") - print("===============================\n") - - @event.listens_for(dbsession, "after_begin", named=True) - def begin_listener(**kw): - print("\n========= BEGIN =========\n") - print(f"BEGIN was executed\n") - print("===============================\n") - - @event.listens_for(dbsession, "after_rollback", named=True) - def begin_listener(**kw): - print("\n========= ROLLBACK =========\n") - print(f"ROLLBACK was executed\n") - print("===============================\n") - - @event.listens_for(dbsession, "after_commit", named=True) - def begin_listener(**kw): - print("\n========= COMMIT =========\n") - print(f"COMMIT was executed\n") - print("===============================\n") - - -@pytest.fixture() -def override_dbsession_in_route(dbsession, mocker): - """ - Мок для подмены db.session в ручке на тестовую сессию dbsession - """ - mocker.patch.object(db.__class__, "session", property(lambda self: dbsession)) - - @pytest.fixture def authlib_user(): """ diff --git a/tests/test_routes/test_comment.py b/tests/test_routes/test_comment.py index 38ae9e8..166a09d 100644 --- a/tests/test_routes/test_comment.py +++ b/tests/test_routes/test_comment.py @@ -183,9 +183,9 @@ def test_create_comment(client, dbsession, lecturers, body, lecturer_n, response user = UnionAuth.__call__(post_response) acceptable_params = ["Полное имя", "Фото", "Имя пользователя GitHub", "Номер Телефона"] real_params = [i["param"] for i in user.get("userdata")] - for i in real_params: + for param in real_params: assert ( - i in acceptable_params + param in acceptable_params ), f"Не допустимый параметр: \"{i}\"! Список допустимых параметров: {acceptable_params}" assert post_response.status_code == response_status