Feature/auth 002#4
Conversation
mitrandir-pl
left a comment
There was a problem hiding this comment.
Всё надо повыносить в фикстуры. К тестам надо добавить коменты, неясно что вообще тестируется в некоторых.
| def test_generate_email_payload() -> None: | ||
| email_payload = ses_handler.generate_email_payload( | ||
| message="Test message", | ||
| subject="Test subject" | ||
| ) | ||
| assert isinstance(email_payload, EmailPayloadScheme) | ||
| assert isinstance(email_payload.message, str) | ||
| assert isinstance(email_payload.subject, str) |
There was a problem hiding this comment.
что проверяет этот тест? ты по сути проверил что "Test message" и "Test subject" это строки. Чего ради?
There was a problem hiding this comment.
def generate_email_payload(
self,
message: str,
subject: str,
source: str | None = None,
) -> EmailPayloadScheme:
payload = {
'message': message,
'subject': subject,
}
if source:
payload['source'] = source
return EmailPayloadScheme(**payload) функция просто генерирует пейлоад для сообщения, она отдает EmailPayloadScheme где есть поля релевантные тем, что проверялись в тесте, т.е. мне казалось, что нужно проверить: а) создание ответа, б) поля в ответе, но так как EmailPayloadScheme - пайдантик модель - пункт б оверхед. Получается, достаточно оставить что на выходе у меня генерится результат инстанс от модели.
| with patch.object(ses_handler, "generate_email_payload") as mock_gen_payload, \ | ||
| patch.object(ses_handler, "send_email", new_callable=AsyncMock) as mock_send_email, \ | ||
| patch.object(ses_handler, "generate_otp") as mock_generate_otp: | ||
| mock_send_email.return_value = None | ||
| mock_generate_otp.return_value = "TestOTP123" | ||
| mock_gen_payload.return_value = EmailPayloadScheme( | ||
| message="Test message", | ||
| subject="Test subject", | ||
| source="sender@example.com", | ||
| ) |
There was a problem hiding this comment.
ты замокал кучу объектов. Если будут добавляться новые тесты, придётся в них повторять этот код, и так множество раз. Такое надо выносить в фикстуры
There was a problem hiding this comment.
понял, поправил
| with patch.object(ses_handler, "generate_otp") as mock_generate_otp, \ | ||
| patch.object(ses_handler, "send_email", new_callable=AsyncMock) as mock_send_email, \ | ||
| patch.object(msg_creator, "get_ses_confirmation_message") as mock_get_ses_message, \ | ||
| patch.object(redis_client, "set", new_callable=AsyncMock) as mock_set_redis: | ||
| mock_generate_otp.return_value = "TestOTP123" | ||
| mock_get_ses_message.return_value = { | ||
| "message": "test message", | ||
| "subject": "test subject", | ||
| "response_message": "test response", | ||
| } |
There was a problem hiding this comment.
аналогично, такое надо в фикстуры выносить
| auth_data = AuthUserScheme( | ||
| **{ | ||
| "email": "example@email.com", | ||
| "password_hash": "examplePassword123!", | ||
| } | ||
| ) |
There was a problem hiding this comment.
Тут вообще не понимаю в чём прикол? Зачем так объект класса создавать ??
| auth_data = AuthUserScheme( | |
| **{ | |
| "email": "example@email.com", | |
| "password_hash": "examplePassword123!", | |
| } | |
| ) | |
| auth_data = AuthUserScheme( | |
| email="example@email.com", | |
| password_hash="examplePassword123!", | |
| ) |
There was a problem hiding this comment.
согласен, не вспомню уже причину такого оформления)
| } | ||
| ) | ||
| refresh_orm = RefreshTokenORM( | ||
| id=UUID("cfe82c6f-7d8c-4172-bc33-04a24a065c20"), |
There was a problem hiding this comment.
| id=UUID("cfe82c6f-7d8c-4172-bc33-04a24a065c20"), | |
| id=uuid.uuid4(), |
There was a problem hiding this comment.
Почему ты в этом файле делаешь какие-то объекты для тестов. Это же всё надо было делать в фикстурах
There was a problem hiding this comment.
В тестах нет аннотаций типов, надо добавить
| return_value=token_data, | ||
| ) | ||
| mock_dependencies["token_repo"].update_refresh.return_value = refresh_orm | ||
| token_service = TokenService(**mock_dependencies) | ||
| res = await token_service.exchange_refresh_token(token_data=token_data) |
There was a problem hiding this comment.
тесты получились крайне непонятными, что за токен дата, откуда она взялась. Аннотаций типов нет, коментов нет.
| "auth_app.services.users.msg_creator.get_code_message", | ||
| return_value="Code sent", | ||
| ) | ||
| user_service = UserService(**mock_dependencies) |
There was a problem hiding this comment.
опять-таки, ты в каждом тесте этот сервис создаёшь, почему тогда не вынести это в фикстуру?
| def test_hash_password() -> None: | ||
| hashed_password = hash_password(pwd) | ||
| assert isinstance(hashed_password, str) |
There was a problem hiding this comment.
нет никакого смысла проверять тип, проверять надо логику
There was a problem hiding this comment.
тут сложно что-то глубоко проверить тк на базе либы хеширую, т.е. я базово чекнул что результат хеширования нужный мне тип и добавил верификацию в данный тест
| email = "email@example.com" | ||
| pwd = "12345Password!" | ||
| hashed_pwd = hash_password(pwd) |
There was a problem hiding this comment.
почему это не фикстуры
| self.__redis = redis # pylint: disable=W0238 | ||
| self.__ses = ses # pylint: disable=W0238 |
There was a problem hiding this comment.
А зачем тебе поля которые ты не используешь?
There was a problem hiding this comment.
почему-то думал, что буду их тоже юзать, поэтому делал заглушки. сейчас убрал.
| @pytest.fixture | ||
| def mock_dependencies() -> dict: | ||
| return { | ||
| "user_repo": Mock( | ||
| create_user=AsyncMock(), | ||
| get_user=AsyncMock(), | ||
| update_user=AsyncMock(), | ||
| get_users=AsyncMock(), | ||
| ), | ||
| "token_repo": Mock( | ||
| create_refresh=AsyncMock(), | ||
| get_refresh=AsyncMock(), | ||
| update_refresh=AsyncMock(), | ||
| ), | ||
| "redis": Mock(), | ||
| "ses": Mock( | ||
|
|
||
| ), | ||
| } |
There was a problem hiding this comment.
видимо забыл удалить, но старайся перепроверять такие штуки
There was a problem hiding this comment.
точно, сори, поправил
| @pytest.fixture(scope="session") | ||
| def user_id() -> UUID: | ||
| return uuid4() |
There was a problem hiding this comment.
я не вижу ни одного теста для которого это было бы необходимо. Можно просто обойтись uuid4()
There was a problem hiding this comment.
идея была в том, чтобы просто 1 раз создать uuid и переиспользовать его, как это делаю с имейлом, паролем и другими данными для юзера. пусть будет так в этом сервисе, если ты не против, в других учту момент
| assert email_payload.message == "Test message" | ||
| assert email_payload.subject == "Test subject" |
There was a problem hiding this comment.
непонятно откуда данные вылазят
правильнее было бы так
| assert email_payload.message == "Test message" | |
| assert email_payload.subject == "Test subject" | |
| assert email_payload.message == generate_email_payload_data["message"] | |
| assert email_payload.subject == generate_email_payload_data["subject"] |
There was a problem hiding this comment.
полностью поддерживаю, проглядел
|
|
||
|
|
||
| def test_generate_email_payload( | ||
| generate_email_payload_data, |
There was a problem hiding this comment.
почему нет аннотаций типов
There was a problem hiding this comment.
все поправил
| send_email_patch, | ||
| get_user_data, |
There was a problem hiding this comment.
Аннотации типов, и так везде
There was a problem hiding this comment.
все поправил
| role_auth_data = RoleDataScheme( | ||
| **auth_user_data_mock.model_dump(), | ||
| ) |
There was a problem hiding this comment.
здесь точно надо так создавать объект? а то опять через словарь и нифига неясно какие там поля
There was a problem hiding this comment.
в этом, мне кажется, есть логика, поясню:
RoleDataScheme - расширенная схема AuthUserScheme (где кроме имейла и пароля есть ролевые данные),
но они не являются обязательными и имеют дефолты, поэтому я от базового класса (он уже мокнут) делаю дамп для дикта и просто прокидываю данные необходимые, а остальные - дефолт тянут
There was a problem hiding this comment.
я ничего не понял. Переделай под нормальное создание. Явность всегда важнее чем то что ты описываешь. А здесь нифига не явно. Плюс, меняется схема -> ломаются такие создания объектов. А что там сломалось - непонятно, так как создание неявное
| env: | ||
| #POSTGRES | ||
| POSTGRES_DB: default_db | ||
| POSTGRES_USER: default_user | ||
| POSTGRES_PASSWORD: default_password | ||
| POSTGRES_HOST: localhost | ||
| POSTGRES_PORT: '5438' | ||
| # REDIS | ||
| REDIS_PASSWORD: default_password | ||
| REDIS_PORT: 6380 | ||
| REDIS_HOST: localhost | ||
| # PASSWORD HASHING | ||
| HASHING_ALGORITHM: bcrypt | ||
| HASHING_DEPRECATED: auto | ||
| # JWT SECRET KEY | ||
| KEY: secret_key | ||
| ALGORITHM: HS256 | ||
| REFRESH_LASTING: 3000 | ||
| ACCESS_LASTING: 300 | ||
| ADMIN_SECRET: default_secret | ||
| # LOCALSTACK | ||
| SERVICES: ses,s3 | ||
| AWS_DEFAULT_REGION: us-east-1 | ||
| LOCALSTACK_HOST: localstack | ||
| DEBUG: 1 | ||
| AWS_ACCESS_KEY_ID: test | ||
| AWS_SECRET_ACCESS_KEY: test | ||
| # LOCAL AWS | ||
| AWS_ENDPOINT: http://localhost:4566 | ||
| RESET_PWD_LENGTH: 10 | ||
| VERIFICATION_CODE_LENGTH: 5 |
There was a problem hiding this comment.
почему переменные энва прямо в файле хранятся
| - name: Install requirements | ||
| run: | | ||
| python -m pip install --upgrade pip | ||
| pip install poetry | ||
| poetry config virtualenvs.create false | ||
| poetry install |
There was a problem hiding this comment.
надо ещё покрытие проверять, если < 80, то пайплайн должен падать
| role_auth_data = RoleDataScheme( | ||
| **auth_user_data_mock.model_dump(), | ||
| ) |
There was a problem hiding this comment.
я ничего не понял. Переделай под нормальное создание. Явность всегда важнее чем то что ты описываешь. А здесь нифига не явно. Плюс, меняется схема -> ломаются такие создания объектов. А что там сломалось - непонятно, так как создание неявное
No description provided.