You've already forked RekomenciBackend
feat(): unit tests for domain entities and basic invariants
This commit is contained in:
+10
-10
@@ -1,25 +1,26 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import subprocess
|
import subprocess # noqa: S404
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from template_project.web_api.configuration import load_configuration
|
from template_project.web_api.configuration import load_configuration
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
config_path = Path("config.toml")
|
config_path = Path("config.toml")
|
||||||
configuration = load_configuration(config_path)
|
configuration = load_configuration(config_path)
|
||||||
|
|
||||||
db_url = str(configuration.database.url.get_value())
|
db_url = str(configuration.database.url.get_value())
|
||||||
db_url = db_url.replace("postgresql+psycopg://", "postgresql://")
|
db_url = db_url.replace("postgresql+psycopg://", "postgresql://")
|
||||||
|
|
||||||
output_dir = Path("dumps")
|
output_dir = Path("dumps")
|
||||||
output_dir.mkdir(exist_ok=True)
|
output_dir.mkdir(exist_ok=True)
|
||||||
|
|
||||||
output_file = output_dir / "data_dump.sql"
|
output_file = output_dir / "data_dump.sql"
|
||||||
|
|
||||||
print("Создание дампа таблиц vacancy, vacancy_embedding, key_skills...")
|
print("Создание дампа таблиц vacancy, vacancy_embedding, key_skills...")
|
||||||
|
|
||||||
subprocess.run(
|
subprocess.run( # noqa: S603
|
||||||
[
|
[ # noqa: S607
|
||||||
"pg_dump",
|
"pg_dump",
|
||||||
db_url,
|
db_url,
|
||||||
"--table=vacancy",
|
"--table=vacancy",
|
||||||
@@ -31,7 +32,7 @@ def main() -> None:
|
|||||||
],
|
],
|
||||||
check=True,
|
check=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
print(f"\nДамп создан: {output_file}")
|
print(f"\nДамп создан: {output_file}")
|
||||||
print(f"Размер файла: {output_file.stat().st_size / 1024 / 1024:.2f} MB")
|
print(f"Размер файла: {output_file.stat().st_size / 1024 / 1024:.2f} MB")
|
||||||
print("\nДля импорта на прод сервере выполните:")
|
print("\nДля импорта на прод сервере выполните:")
|
||||||
@@ -40,4 +41,3 @@ def main() -> None:
|
|||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
|||||||
@@ -93,8 +93,8 @@ class ExperienceTypeType(TypeDecorator[ExperienceType]):
|
|||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
try:
|
try:
|
||||||
return ExperienceType(value)
|
return ExperienceType(value)
|
||||||
except ValueError:
|
except ValueError as err:
|
||||||
raise ValueError(f"Invalid experience_type value: {value}")
|
raise ValueError(f"Invalid experience_type value: {value}") from err
|
||||||
raise ValueError(f"Cannot convert {type(value)} to ExperienceType")
|
raise ValueError(f"Cannot convert {type(value)} to ExperienceType")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
from datetime import UTC, datetime, timedelta
|
||||||
|
from uuid import UUID, uuid4
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from template_project.application.access_token.entity import AccessToken
|
||||||
|
from template_project.application.access_token.errors import AccessTokenExpiredError
|
||||||
|
from template_project.application.user.entity import UserId
|
||||||
|
|
||||||
|
|
||||||
|
def test_access_token_factory_creates_valid_token() -> None:
|
||||||
|
user_id = UserId(uuid4())
|
||||||
|
expires_in = timedelta(days=7)
|
||||||
|
|
||||||
|
token = AccessToken.factory(
|
||||||
|
user_id=user_id,
|
||||||
|
expires_in=expires_in,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert isinstance(token.id, UUID)
|
||||||
|
assert token.user_id == user_id
|
||||||
|
assert token.revoked is False
|
||||||
|
assert token.expires_in > datetime.now(tz=UTC)
|
||||||
|
assert token.deleted_at is None
|
||||||
|
assert token.created_at.tzinfo == UTC
|
||||||
|
|
||||||
|
|
||||||
|
def test_access_token_expired_predicate_not_expired() -> None:
|
||||||
|
user_id = UserId(uuid4())
|
||||||
|
token = AccessToken.factory(
|
||||||
|
user_id=user_id,
|
||||||
|
expires_in=timedelta(days=7),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not token.expired_predicate()
|
||||||
|
|
||||||
|
|
||||||
|
def test_access_token_expired_predicate_expired_by_time() -> None:
|
||||||
|
user_id = UserId(uuid4())
|
||||||
|
token = AccessToken.factory(
|
||||||
|
user_id=user_id,
|
||||||
|
expires_in=timedelta(days=-1),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert token.expired_predicate()
|
||||||
|
|
||||||
|
|
||||||
|
def test_access_token_expired_predicate_revoked() -> None:
|
||||||
|
user_id = UserId(uuid4())
|
||||||
|
token = AccessToken.factory(
|
||||||
|
user_id=user_id,
|
||||||
|
expires_in=timedelta(days=7),
|
||||||
|
)
|
||||||
|
token.revoke()
|
||||||
|
|
||||||
|
assert token.expired_predicate()
|
||||||
|
|
||||||
|
|
||||||
|
def test_access_token_ensure_expired_raises_when_expired() -> None:
|
||||||
|
user_id = UserId(uuid4())
|
||||||
|
token = AccessToken.factory(
|
||||||
|
user_id=user_id,
|
||||||
|
expires_in=timedelta(days=-1),
|
||||||
|
)
|
||||||
|
|
||||||
|
with pytest.raises(AccessTokenExpiredError):
|
||||||
|
token.ensure_expired()
|
||||||
|
|
||||||
|
|
||||||
|
def test_access_token_ensure_expired_raises_when_revoked() -> None:
|
||||||
|
user_id = UserId(uuid4())
|
||||||
|
token = AccessToken.factory(
|
||||||
|
user_id=user_id,
|
||||||
|
expires_in=timedelta(days=7),
|
||||||
|
)
|
||||||
|
token.revoke()
|
||||||
|
|
||||||
|
with pytest.raises(AccessTokenExpiredError):
|
||||||
|
token.ensure_expired()
|
||||||
|
|
||||||
|
|
||||||
|
def test_access_token_revoke() -> None:
|
||||||
|
user_id = UserId(uuid4())
|
||||||
|
token = AccessToken.factory(
|
||||||
|
user_id=user_id,
|
||||||
|
expires_in=timedelta(days=7),
|
||||||
|
)
|
||||||
|
|
||||||
|
token.revoke()
|
||||||
|
|
||||||
|
assert token.revoked is True
|
||||||
|
assert token.deleted_at is not None
|
||||||
|
assert token.deleted_at.tzinfo == UTC
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
from datetime import UTC
|
||||||
|
from uuid import UUID, uuid4
|
||||||
|
|
||||||
|
from template_project.application.auth_identity.entity import AuthIdentity, AuthMethod
|
||||||
|
from template_project.application.user.entity import UserId
|
||||||
|
|
||||||
|
|
||||||
|
def test_auth_identity_factory_creates_valid_identity() -> None:
|
||||||
|
user_id = UserId(uuid4())
|
||||||
|
|
||||||
|
identity = AuthIdentity.factory(
|
||||||
|
user_id=user_id,
|
||||||
|
method=AuthMethod.EMAIL,
|
||||||
|
identifier="test@example.com",
|
||||||
|
secret_key="hashed_password",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert isinstance(identity.id, UUID)
|
||||||
|
assert identity.user_id == user_id
|
||||||
|
assert identity.method == AuthMethod.EMAIL
|
||||||
|
assert identity.identifier == "test@example.com"
|
||||||
|
assert identity.secret_key == "hashed_password" # noqa: S105
|
||||||
|
assert identity.deleted_at is None
|
||||||
|
assert identity.created_at.tzinfo == UTC
|
||||||
|
|
||||||
|
|
||||||
|
def test_auth_identity_factory_without_secret_key() -> None:
|
||||||
|
user_id = UserId(uuid4())
|
||||||
|
|
||||||
|
identity = AuthIdentity.factory(
|
||||||
|
user_id=user_id,
|
||||||
|
method=AuthMethod.YANDEX,
|
||||||
|
identifier="yandex_id_123",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert identity.secret_key is None
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
from datetime import UTC
|
||||||
|
from uuid import UUID, uuid4
|
||||||
|
|
||||||
|
from template_project.application.notification_device.entity import NotificationDevice
|
||||||
|
from template_project.application.user.entity import UserId
|
||||||
|
|
||||||
|
|
||||||
|
def test_notification_device_factory_creates_valid_device() -> None:
|
||||||
|
user_id = UserId(uuid4())
|
||||||
|
|
||||||
|
device = NotificationDevice.factory(
|
||||||
|
user_id=user_id,
|
||||||
|
device_id="device_123",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert isinstance(device.id, UUID)
|
||||||
|
assert device.user_id == user_id
|
||||||
|
assert device.device_id == "device_123"
|
||||||
|
assert device.deleted_at is None
|
||||||
|
assert device.created_at.tzinfo == UTC
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
from datetime import UTC
|
||||||
|
from uuid import UUID, uuid4
|
||||||
|
|
||||||
|
from template_project.application.user.entity import UserId
|
||||||
|
from template_project.application.user.profile.entity import Profile
|
||||||
|
|
||||||
|
|
||||||
|
def test_profile_factory_creates_valid_profile() -> None:
|
||||||
|
user_id = UserId(uuid4())
|
||||||
|
|
||||||
|
profile = Profile.factory(
|
||||||
|
user_id=user_id,
|
||||||
|
email="test@example.com",
|
||||||
|
display_name="Test User",
|
||||||
|
first_name="Test",
|
||||||
|
last_name="User",
|
||||||
|
avatar_url="https://example.com/avatar.jpg",
|
||||||
|
phone="+1234567890",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert isinstance(profile.id, UUID)
|
||||||
|
assert profile.user_id == user_id
|
||||||
|
assert profile.email == "test@example.com"
|
||||||
|
assert profile.display_name == "Test User"
|
||||||
|
assert profile.first_name == "Test"
|
||||||
|
assert profile.last_name == "User"
|
||||||
|
assert profile.avatar_url == "https://example.com/avatar.jpg"
|
||||||
|
assert profile.phone == "+1234567890"
|
||||||
|
assert profile.deleted_at is None
|
||||||
|
assert profile.created_at.tzinfo == UTC
|
||||||
|
|
||||||
|
|
||||||
|
def test_profile_factory_with_minimal_fields() -> None:
|
||||||
|
user_id = UserId(uuid4())
|
||||||
|
|
||||||
|
profile = Profile.factory(user_id=user_id)
|
||||||
|
|
||||||
|
assert profile.user_id == user_id
|
||||||
|
assert profile.email is None
|
||||||
|
assert profile.display_name is None
|
||||||
|
assert profile.first_name is None
|
||||||
|
assert profile.last_name is None
|
||||||
|
assert profile.avatar_url is None
|
||||||
|
assert profile.phone is None
|
||||||
@@ -0,0 +1,229 @@
|
|||||||
|
from datetime import UTC
|
||||||
|
from decimal import Decimal
|
||||||
|
from uuid import UUID, uuid4
|
||||||
|
|
||||||
|
from template_project.application.common.enums import EducationGrade, ExperienceType
|
||||||
|
from template_project.application.resume.entity import (
|
||||||
|
Resume,
|
||||||
|
ResumeEducation,
|
||||||
|
ResumeEmbedding,
|
||||||
|
ResumeExperience,
|
||||||
|
ResumeId,
|
||||||
|
ResumePrediction,
|
||||||
|
ResumeProject,
|
||||||
|
)
|
||||||
|
from template_project.application.user.entity import UserId
|
||||||
|
|
||||||
|
|
||||||
|
def test_resume_factory_creates_valid_resume() -> None:
|
||||||
|
user_id = UserId(uuid4())
|
||||||
|
resume = Resume.factory(
|
||||||
|
user_id=user_id,
|
||||||
|
position="Python Developer",
|
||||||
|
location="Moscow",
|
||||||
|
about_me="Experienced developer",
|
||||||
|
key_skills=["Python", "FastAPI"],
|
||||||
|
experience_type=ExperienceType.BETWEEN_3_AND_6,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert isinstance(resume.id, UUID)
|
||||||
|
assert resume.user_id == user_id
|
||||||
|
assert resume.position == "Python Developer"
|
||||||
|
assert resume.location == "Moscow"
|
||||||
|
assert resume.about_me == "Experienced developer"
|
||||||
|
assert resume.key_skills == ["Python", "FastAPI"]
|
||||||
|
assert resume.experience_type == ExperienceType.BETWEEN_3_AND_6
|
||||||
|
assert resume.down_resume_id is None
|
||||||
|
assert resume.up_resume_id is None
|
||||||
|
assert resume.deleted_at is None
|
||||||
|
assert resume.created_at.tzinfo == UTC
|
||||||
|
|
||||||
|
|
||||||
|
def test_resume_factory_with_history_links() -> None:
|
||||||
|
user_id = UserId(uuid4())
|
||||||
|
old_resume_id = ResumeId(uuid4())
|
||||||
|
|
||||||
|
resume = Resume.factory(
|
||||||
|
user_id=user_id,
|
||||||
|
position="Python Developer",
|
||||||
|
location="Moscow",
|
||||||
|
about_me="Updated",
|
||||||
|
key_skills=["Python"],
|
||||||
|
experience_type=ExperienceType.BETWEEN_3_AND_6,
|
||||||
|
down_resume_id=old_resume_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert resume.down_resume_id == old_resume_id
|
||||||
|
|
||||||
|
|
||||||
|
def test_resume_embedding_factory_creates_valid_embedding() -> None:
|
||||||
|
resume_id = ResumeId(uuid4())
|
||||||
|
vector = [0.1, 0.2, 0.3, 0.4, 0.5]
|
||||||
|
|
||||||
|
embedding = ResumeEmbedding.factory(
|
||||||
|
resume_id=resume_id,
|
||||||
|
vector=vector,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert isinstance(embedding.id, UUID)
|
||||||
|
assert embedding.resume_id == resume_id
|
||||||
|
assert embedding.vector == vector
|
||||||
|
assert embedding.deleted_at is None
|
||||||
|
assert embedding.created_at.tzinfo == UTC
|
||||||
|
|
||||||
|
|
||||||
|
def test_resume_embedding_vector_dimension() -> None:
|
||||||
|
resume_id = ResumeId(uuid4())
|
||||||
|
vector = [0.1] * 384
|
||||||
|
|
||||||
|
embedding = ResumeEmbedding.factory(
|
||||||
|
resume_id=resume_id,
|
||||||
|
vector=vector,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(embedding.vector) == 384
|
||||||
|
assert all(isinstance(x, float) for x in embedding.vector)
|
||||||
|
|
||||||
|
|
||||||
|
def test_resume_prediction_factory_creates_valid_prediction() -> None:
|
||||||
|
resume_id = ResumeId(uuid4())
|
||||||
|
|
||||||
|
prediction = ResumePrediction.factory(
|
||||||
|
resume_id=resume_id,
|
||||||
|
from_salary=Decimal(100000),
|
||||||
|
to_salary=Decimal(150000),
|
||||||
|
recommended_skills=["Kubernetes", "Docker"],
|
||||||
|
)
|
||||||
|
|
||||||
|
assert isinstance(prediction.id, UUID)
|
||||||
|
assert prediction.resume_id == resume_id
|
||||||
|
assert prediction.from_salary == Decimal(100000)
|
||||||
|
assert prediction.to_salary == Decimal(150000)
|
||||||
|
assert prediction.recommended_skills == ["Kubernetes", "Docker"]
|
||||||
|
assert prediction.deleted_at is None
|
||||||
|
assert prediction.created_at.tzinfo == UTC
|
||||||
|
|
||||||
|
|
||||||
|
def test_resume_prediction_salary_order() -> None:
|
||||||
|
resume_id = ResumeId(uuid4())
|
||||||
|
|
||||||
|
prediction = ResumePrediction.factory(
|
||||||
|
resume_id=resume_id,
|
||||||
|
from_salary=Decimal(100000),
|
||||||
|
to_salary=Decimal(150000),
|
||||||
|
recommended_skills=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
assert prediction.from_salary <= prediction.to_salary
|
||||||
|
|
||||||
|
|
||||||
|
def test_resume_prediction_empty_recommended_skills() -> None:
|
||||||
|
resume_id = ResumeId(uuid4())
|
||||||
|
|
||||||
|
prediction = ResumePrediction.factory(
|
||||||
|
resume_id=resume_id,
|
||||||
|
from_salary=Decimal(100000),
|
||||||
|
to_salary=Decimal(150000),
|
||||||
|
recommended_skills=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
assert prediction.recommended_skills == []
|
||||||
|
|
||||||
|
|
||||||
|
def test_resume_experience_positive_duration() -> None:
|
||||||
|
resume_id = ResumeId(uuid4())
|
||||||
|
|
||||||
|
experience = ResumeExperience.factory(
|
||||||
|
resume_id=resume_id,
|
||||||
|
place="Company",
|
||||||
|
description="Work",
|
||||||
|
months_duration=12,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert experience.months_duration > 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_resume_key_skills_empty_list() -> None:
|
||||||
|
user_id = UserId(uuid4())
|
||||||
|
|
||||||
|
resume = Resume.factory(
|
||||||
|
user_id=user_id,
|
||||||
|
position="Developer",
|
||||||
|
location="Moscow",
|
||||||
|
about_me="Test",
|
||||||
|
key_skills=[],
|
||||||
|
experience_type=ExperienceType.NO_EXPERIENCE,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert resume.key_skills == []
|
||||||
|
|
||||||
|
|
||||||
|
def test_resume_experience_factory_creates_valid_experience() -> None:
|
||||||
|
resume_id = ResumeId(uuid4())
|
||||||
|
|
||||||
|
experience = ResumeExperience.factory(
|
||||||
|
resume_id=resume_id,
|
||||||
|
place="T-bank",
|
||||||
|
description="Backend development",
|
||||||
|
months_duration=24,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert isinstance(experience.id, UUID)
|
||||||
|
assert experience.resume_id == resume_id
|
||||||
|
assert experience.place == "T-bank"
|
||||||
|
assert experience.description == "Backend development"
|
||||||
|
assert experience.months_duration == 24
|
||||||
|
assert experience.months_duration > 0
|
||||||
|
assert experience.deleted_at is None
|
||||||
|
assert experience.created_at.tzinfo == UTC
|
||||||
|
|
||||||
|
|
||||||
|
def test_resume_education_factory_creates_valid_education() -> None:
|
||||||
|
resume_id = ResumeId(uuid4())
|
||||||
|
|
||||||
|
education = ResumeEducation.factory(
|
||||||
|
resume_id=resume_id,
|
||||||
|
place="University",
|
||||||
|
grade=EducationGrade.BACHELOR,
|
||||||
|
specialization="Computer Science",
|
||||||
|
description="Optional description",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert isinstance(education.id, UUID)
|
||||||
|
assert education.resume_id == resume_id
|
||||||
|
assert education.place == "University"
|
||||||
|
assert education.grade == EducationGrade.BACHELOR
|
||||||
|
assert education.specialization == "Computer Science"
|
||||||
|
assert education.description == "Optional description"
|
||||||
|
assert education.deleted_at is None
|
||||||
|
assert education.created_at.tzinfo == UTC
|
||||||
|
|
||||||
|
|
||||||
|
def test_resume_education_factory_without_description() -> None:
|
||||||
|
resume_id = ResumeId(uuid4())
|
||||||
|
|
||||||
|
education = ResumeEducation.factory(
|
||||||
|
resume_id=resume_id,
|
||||||
|
place="University",
|
||||||
|
grade=EducationGrade.MASTER,
|
||||||
|
specialization="Data Science",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert education.description is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_resume_project_factory_creates_valid_project() -> None:
|
||||||
|
resume_id = ResumeId(uuid4())
|
||||||
|
|
||||||
|
project = ResumeProject.factory(
|
||||||
|
resume_id=resume_id,
|
||||||
|
name="ML Service",
|
||||||
|
description="Machine learning service",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert isinstance(project.id, UUID)
|
||||||
|
assert project.resume_id == resume_id
|
||||||
|
assert project.name == "ML Service"
|
||||||
|
assert project.description == "Machine learning service"
|
||||||
|
assert project.deleted_at is None
|
||||||
|
assert project.created_at.tzinfo == UTC
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
from datetime import UTC
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
|
from template_project.application.user.entity import User
|
||||||
|
|
||||||
|
|
||||||
|
def test_user_factory_creates_valid_user() -> None:
|
||||||
|
user = User.factory()
|
||||||
|
|
||||||
|
assert isinstance(user.id, UUID)
|
||||||
|
assert user.deleted_at is None
|
||||||
|
assert user.created_at.tzinfo == UTC
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
from datetime import UTC
|
||||||
|
from decimal import Decimal
|
||||||
|
from uuid import UUID, uuid4
|
||||||
|
|
||||||
|
from template_project.application.common.enums import ExperienceType
|
||||||
|
from template_project.application.vacancy.entity import Vacancy, VacancyEmbedding, VacancyId
|
||||||
|
|
||||||
|
|
||||||
|
def test_vacancy_factory_creates_valid_vacancy() -> None:
|
||||||
|
vacancy = Vacancy.factory(
|
||||||
|
position="Python Developer",
|
||||||
|
from_salary=Decimal(100000),
|
||||||
|
to_salary=Decimal(150000),
|
||||||
|
experience_type=ExperienceType.BETWEEN_3_AND_6,
|
||||||
|
description="Backend development",
|
||||||
|
key_skills=["Python", "FastAPI"],
|
||||||
|
)
|
||||||
|
|
||||||
|
assert isinstance(vacancy.id, UUID)
|
||||||
|
assert vacancy.position == "Python Developer"
|
||||||
|
assert vacancy.from_salary == Decimal(100000)
|
||||||
|
assert vacancy.to_salary == Decimal(150000)
|
||||||
|
assert vacancy.experience_type == ExperienceType.BETWEEN_3_AND_6
|
||||||
|
assert vacancy.description == "Backend development"
|
||||||
|
assert vacancy.key_skills == ["Python", "FastAPI"]
|
||||||
|
assert vacancy.deleted_at is None
|
||||||
|
assert vacancy.created_at.tzinfo == UTC
|
||||||
|
|
||||||
|
|
||||||
|
def test_vacancy_salary_order() -> None:
|
||||||
|
vacancy = Vacancy.factory(
|
||||||
|
position="Developer",
|
||||||
|
from_salary=Decimal(100000),
|
||||||
|
to_salary=Decimal(150000),
|
||||||
|
experience_type=ExperienceType.BETWEEN_1_AND_3,
|
||||||
|
description="Test",
|
||||||
|
key_skills=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
assert vacancy.from_salary <= vacancy.to_salary
|
||||||
|
|
||||||
|
|
||||||
|
def test_vacancy_equal_salaries() -> None:
|
||||||
|
vacancy = Vacancy.factory(
|
||||||
|
position="Developer",
|
||||||
|
from_salary=Decimal(100000),
|
||||||
|
to_salary=Decimal(100000),
|
||||||
|
experience_type=ExperienceType.BETWEEN_1_AND_3,
|
||||||
|
description="Test",
|
||||||
|
key_skills=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
assert vacancy.from_salary == vacancy.to_salary
|
||||||
|
|
||||||
|
|
||||||
|
def test_vacancy_empty_key_skills() -> None:
|
||||||
|
vacancy = Vacancy.factory(
|
||||||
|
position="Developer",
|
||||||
|
from_salary=Decimal(100000),
|
||||||
|
to_salary=Decimal(150000),
|
||||||
|
experience_type=ExperienceType.NO_EXPERIENCE,
|
||||||
|
description="Test",
|
||||||
|
key_skills=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
assert vacancy.key_skills == []
|
||||||
|
|
||||||
|
|
||||||
|
def test_vacancy_embedding_vector_dimension() -> None:
|
||||||
|
vacancy_id = VacancyId(uuid4())
|
||||||
|
vector = [0.1] * 384
|
||||||
|
|
||||||
|
embedding = VacancyEmbedding.factory(
|
||||||
|
vacancy_id=vacancy_id,
|
||||||
|
vector=vector,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(embedding.vector) == 384
|
||||||
|
assert all(isinstance(x, float) for x in embedding.vector)
|
||||||
|
|
||||||
|
|
||||||
|
def test_vacancy_embedding_factory_creates_valid_embedding() -> None:
|
||||||
|
vacancy_id = VacancyId(uuid4())
|
||||||
|
vector = [0.1, 0.2, 0.3, 0.4, 0.5]
|
||||||
|
|
||||||
|
embedding = VacancyEmbedding.factory(
|
||||||
|
vacancy_id=vacancy_id,
|
||||||
|
vector=vector,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert isinstance(embedding.id, UUID)
|
||||||
|
assert embedding.vacancy_id == vacancy_id
|
||||||
|
assert embedding.vector == vector
|
||||||
|
assert embedding.deleted_at is None
|
||||||
|
assert embedding.created_at.tzinfo == UTC
|
||||||
Reference in New Issue
Block a user