Skip to content
This repository has been archived by the owner on Mar 19, 2024. It is now read-only.

Feature/python testing homework #57

Open
wants to merge 60 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
91b3d52
feta: add mimesis to poetry
Sep 16, 2023
63829d4
feta: add tests for placeholder module
Sep 16, 2023
a7bb432
feta: add protocols module
Sep 16, 2023
98b438d
feta: add fixtures for tests
Sep 16, 2023
1b84666
refactor: move files
Sep 16, 2023
2d45717
feat: add mock settings
Sep 16, 2023
0693c44
refactor: move protocols
Sep 16, 2023
3ae8d67
refactor: remove extra fixture
Sep 16, 2023
941e2f4
refactor: del typehint to resole import error
Sep 16, 2023
f8fcbc4
feat: add tests for user_create_new.py
Sep 16, 2023
873ed29
refactor: rename new_ids to response, because its UserResponse
Sep 16, 2023
577859c
style: change double quotes to single
Sep 16, 2023
2c77850
style: fix pipeline comments
Sep 16, 2023
f2cfe57
wtf
Sep 16, 2023
21330d0
feat: add test for url_path method
Sep 16, 2023
75f0952
feat: add init for tests
Sep 16, 2023
0f446e9
feat: add type annotation
Sep 16, 2023
188743d
feat: move protocols to plugins
Sep 16, 2023
89faa6e
feat: move protocols to plugins
Sep 16, 2023
e815cd0
feat: add annotations
Sep 16, 2023
e970b74
feat: change import path
Sep 16, 2023
7f513e9
feat: unuse plugin
Sep 16, 2023
b5f96f1
feat: move to plugins
Sep 16, 2023
0337705
feat: add test for _UserManager
Sep 16, 2023
889f180
refactor: change type path
Sep 16, 2023
b20eb6a
refactor: move types to plugins
Sep 16, 2023
3f7952d
refactor: add docstrings and fix pipeline issues
Sep 16, 2023
764029b
refactor: try to fix pipeline issues
Sep 16, 2023
49ecefb
style: use isort
Sep 16, 2023
747684d
feat: add isort lib
Sep 16, 2023
f8f5bb9
fix: try to fix pipelin
Sep 16, 2023
e07740b
fix: try to fix pipeline
Sep 16, 2023
257a5a9
fix: try to fix pipeline
Sep 16, 2023
ff273a3
fix: try to fix pipeline
Sep 16, 2023
7946c12
fix: try to fix pipeline
Sep 16, 2023
fa37aab
fix: try to fix pipeline
Sep 16, 2023
d66bc12
fix: try to fix pipeline
Sep 16, 2023
abe1699
fix: try to fix pipeline
Sep 16, 2023
8e7449b
fix: try to fix pipeline
Sep 16, 2023
c72efe1
refactor: remove extra files
Sep 22, 2023
94e3ca8
feat: registrate a new plugin
Sep 22, 2023
d94f101
refactor: make assertion simple
Sep 22, 2023
8d1e7fc
refactor: move user fixture to plugin
Sep 22, 2023
c2f0b81
feat: add httpretty to poetry
Sep 22, 2023
42b901a
feat: add new fixtures for tests
Sep 22, 2023
a140df8
feat: add assert not lead user
Sep 22, 2023
613da1e
feat: change deprecated method
Sep 22, 2023
f522e09
feat: add fixtures for picture tests
Sep 22, 2023
dfd0357
feat: add new plugins picture
Sep 23, 2023
6143d15
feat: add pictures data factory, picture types and fixtures for testing
Sep 23, 2023
4c32e52
feat: add tests for pictures
Sep 23, 2023
5606ac5
feat: add failed_pydantic_fields fixture and import test_success_vali…
Sep 23, 2023
f842aa0
feat: make dit hierarchy more flatten
Sep 23, 2023
6c02234
refactor: mar django test for whole module
Sep 23, 2023
6e8e430
feat: add tests for user views
Sep 23, 2023
4f243a0
feat: add auth client fixture
Sep 23, 2023
9958c85
feat: reg new plugin for mark slow tests
Sep 23, 2023
1c25f00
feat: add pytest options
Sep 23, 2023
941971d
feat: add slow test plugin
Sep 23, 2023
949c222
feat: mark slow tests
Sep 23, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 44 additions & 2 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ requests = "^2.28"
attrs = "^23.1"
pydantic = "^2.3"
punq = "^0.6"
mimesis = "^11.1.0"
isort = "^5.12.0"
Hyper-glitch marked this conversation as resolved.
Show resolved Hide resolved
httpretty = "^1.1.4"

[tool.poetry.group.dev.dependencies]
django-debug-toolbar = "^4.2"
Expand Down Expand Up @@ -93,3 +96,7 @@ format_attribute_template_tags = true

[tool.nitpick]
style = "https://raw.githubusercontent.com/wemake-services/wemake-python-styleguide/0.18.0/styles/nitpick-style-wemake.toml"


[tool.pytest.ini_options]
DJANGO_SETTINGS_MODULE = "server.settings"
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def __call__(
timeout=self._api_timeout,
)
response.raise_for_status()
return UserResponse.parse_raw(response.text)
return UserResponse.model_validate_json(response.text)


@final
Expand Down
6 changes: 3 additions & 3 deletions server/apps/identity/logic/usecases/user_create_new.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def __call__(self, user: User) -> None:
https://sobolevn.me/2019/02/engineering-guide-to-user-stories
"""
new_ids = self._create_lead(user)
return self._update_user_ids(user, new_ids)
self._update_user_ids(user, new_ids)

def _create_lead(self, user: User) -> placeholder.UserResponse:
return placeholder.LeadCreate(
Expand All @@ -41,8 +41,8 @@ def _create_lead(self, user: User) -> placeholder.UserResponse:
def _update_user_ids(
self,
user: User,
new_ids: placeholder.UserResponse,
response: placeholder.UserResponse,
) -> None:
# This can be moved to some other place once this becomes too complex:
user.lead_id = new_ids.id
user.lead_id = response.id
user.save(update_fields=['lead_id'])
File renamed without changes.
8 changes: 4 additions & 4 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
"""

pytest_plugins = [
# Should be the first custom one:
'plugins.django_settings',

# TODO: add your own plugins here!
'tests.plugins.django_settings',
'tests.plugins.identity.user',
'tests.plugins.pictures.pictures',
'tests.plugins.slow',
]
157 changes: 157 additions & 0 deletions tests/plugins/identity/user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import datetime as dt
from typing import Any, Unpack, TYPE_CHECKING
from typing import Callable, Protocol, TypeAlias, TypedDict, final

import pytest
from mimesis import Field, Schema
from mimesis.locales import Locale

from server.apps.identity.intrastructure.services.placeholder import UserResponse
from server.apps.identity.models import User

if TYPE_CHECKING:
from django.test import Client


@final
class UserData(TypedDict, total=False):
"""
Represent the user data that is required to create a new user.

Does not include `password`, because it's special field in Django.
"""

email: str
first_name: str
last_name: str
date_of_birth: dt.datetime
address: str
job_title: str
phone: str
lead_id: int
is_staff: bool
is_active: bool


UserAssertion: TypeAlias = Callable[[str, UserData], None]
NotLeadUserAssertion: TypeAlias = Callable[[str], None]


@final
class RegistrationData(UserData, total=False):
"""Represent the user data that is required to create a new user."""

password_first: str
password_second: str


@final
class RegistrationDataFactory(Protocol):
"""User data factory protocol."""

def __call__(self, **fields: Unpack[RegistrationData]) -> RegistrationData:
"""User data factory protocol."""


@pytest.fixture()
def registration_data_factory() -> RegistrationDataFactory:
"""Fxture that generate fake registration data."""

def factory(**fields: Unpack[RegistrationData]) -> RegistrationData:
field = Field(locale=Locale.RU, seed=fields.pop('seed'))
password = field('password')
schema = Schema(schema=lambda: {
'email': field('person.email'),
'first_name': field('person.first_name'),
'last_name': field('person.last_name'),
'date_of_birth': field('datetime.date'),
'address': field('address.city'),
'job_title': field('person.occupation'),
'phone': field('person.telephone'),
})
return {
**schema.create()[0],
**{'password_first': password, 'password_second': password},
**fields,
}

return factory


@pytest.fixture(scope='session')
def assert_correct_user() -> UserAssertion:
"""Fixture that check created user attrs from database."""

def factory(email: str, expected: UserData) -> None:
user = User.objects.get(email=email)
assert user.id
assert user.is_active
assert not user.is_superuser
assert not user.is_staff
for field, value_name in expected.items():
assert getattr(user, field) == value_name

return factory


@pytest.fixture()
def reg_data(registration_data_factory) -> RegistrationData:
"""Fixture that return user reg data."""
return registration_data_factory(seed=1)
Hyper-glitch marked this conversation as resolved.
Show resolved Hide resolved


@pytest.fixture()
def expected_user_data(reg_data: RegistrationData) -> dict[str, Any]:
"""Fixture that return exeected user data."""
return {
key: value_name
for key, value_name in reg_data.items()
if not key.startswith('password')
}


@pytest.fixture()
def expected_serialized_user(reg_data: RegistrationData) -> dict[str, Any]:
"""Serialized user's key-values that expected in test."""
return {
'name': reg_data['first_name'],
'last_name': reg_data['last_name'],
'birthday': reg_data['date_of_birth'].strftime('%d.%m.%Y'),
'city_of_birth': reg_data['address'],
'position': reg_data['job_title'],
'email': reg_data['email'],
'phone': reg_data['phone'],
}


@pytest.fixture()
def user(
expected_user_data: RegistrationData,
) -> 'User':
"""Return created user in database."""
return User.objects.create(**expected_user_data)


@pytest.fixture()
def expected_user_response(
expected_user_data: RegistrationData,
) -> 'UserResponse':
"""Return user response obj."""
return UserResponse(id=1)


@pytest.fixture(scope='session')
def assert_not_lead_user() -> NotLeadUserAssertion:
"""Check that user is not lead."""
def factory(email: str) -> None:
user = User.objects.get(email=email)
assert user.lead_id is None

return factory


@pytest.fixture()
def authorized_client(client: 'Client', user: 'User') -> 'Client':
"""Authorized User object."""
client.force_login(user)
return client
Loading