-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Расширить использование dirty_equals (#149)
Во время работы над реализацией эндпойнта регистрации (#88), было принято решение использовать библиотеку [freezegun](https://github.com/spulec/freezegun#freezegun-let-your-python-tests-travel-through-time), для поверок данных с динамически генерируемыми датами в тестах. Планировалось в тестах "замораживать" время используя определённую константу, и затем использовать эту константу в проверках. Но в дальнейшем при попытке реализовать эндпойнты файла (#148), выяснилось, что если в тесте мы замораживаем время, а потом посылаем запрос в minio, то сервер minio отклоняет такой запрос с ошибкой, говорящей, что время запроса слишком сильно отличается от времени установленном на сервере. Чтобы решить эту проблему, мы можем использовать библиотеку [dirty_equals](https://dirty-equals.helpmanual.io/latest/) вместо freezegun для проверки динамически генерируемых значений даты и времени в тестах. Так же хотелось бы решить одну небольшую проблему возникающую при использовании dirty_equals - сокрытие примеров значений в ассертах. Например, в таком ассерте визуально не понятно, какое значение (хотя бы примерно) будет в колонке id: ```python assert response.json() == { "id": IsPositiveInt(), "name": "John Doe", } ``` Для этого было принято решение слегка модифицировать классы библиотеки dirty_equals и добавить им возможность указать пример значение через аргумент `like`, т.е.: ```python assert response.json() == { "id": PositiveInt(like=42), "name": "John Doe", } ``` При этом значение указанное в аргументе `like`, так же должно проверятся на соответствие используемому классу, т.е. следующий пример должен давать ошибку: ```python assert response.json() == { "id": PositiveInt(like=-1) "name": "John Doe", } ``` В рамках этой задачи необходимо настроить и использовать dirty_equals для проверок автогенерируемых значений.
- Loading branch information
1 parent
fabec66
commit f69de6b
Showing
6 changed files
with
115 additions
and
55 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
from __future__ import annotations | ||
|
||
from datetime import timezone | ||
from typing import TYPE_CHECKING | ||
|
||
import dirty_equals | ||
|
||
from src.shared.datetime import DATETIME_FORMAT | ||
|
||
|
||
if TYPE_CHECKING: | ||
from datetime import datetime | ||
from typing import Any, Self | ||
|
||
|
||
class PositiveInt(dirty_equals.IsPositiveInt): | ||
|
||
def __init__(self: Self, *, like: int | None = None) -> None: | ||
assert like is not None, "Provide correct example value in `like` argument." | ||
|
||
self._like = like | ||
super().__init__() | ||
|
||
try: | ||
like_equals = self.equals(self._like) | ||
|
||
except TypeError: | ||
msg = f"`like` argument has type {type(self._like)}, but expected {self.allowed_types}." | ||
raise AssertionError(msg) from None | ||
|
||
assert like_equals, "Example value from `like` argument is not correct." | ||
|
||
|
||
class UtcDatetime(dirty_equals.IsDatetime): | ||
|
||
def __init__(self: Self, *, like: datetime | None = None) -> None: | ||
assert like is not None, "Provide correct example value in `like` argument." | ||
|
||
self._like = like | ||
super().__init__(iso_string=False) | ||
|
||
try: | ||
like_equals = self.equals(self._like) | ||
|
||
except TypeError: | ||
msg = f"`like` argument has type {type(self._like)}, but expected {self.allowed_types}." | ||
raise AssertionError(msg) from None | ||
|
||
assert like_equals, "Example value from `like` argument is not correct." | ||
|
||
def equals(self: Self, other: Any) -> bool: # noqa: ANN401 | ||
return super().equals(other) and other.tzinfo == timezone.utc | ||
|
||
|
||
class UtcDatetimeStr(dirty_equals.IsDatetime): | ||
expected_format = DATETIME_FORMAT | ||
|
||
def __init__(self: Self, *, like: str | None = None) -> None: | ||
assert like is not None, "Provide correct example value in `like` argument." | ||
|
||
self._like = like | ||
super().__init__(format_string=self.expected_format) | ||
|
||
try: | ||
like_equals = self.equals(self._like) | ||
|
||
except TypeError: | ||
msg = f"`like` argument has type {type(self._like)}, but expected {self.allowed_types}." | ||
raise AssertionError(msg) from None | ||
|
||
except ValueError: | ||
msg = f"`like` argument '{self._like}' does not match expected format '{self.expected_format}'." | ||
raise AssertionError(msg) from None | ||
|
||
assert like_equals, "Example value from `like` argument is not correct." |