fix(lint): resolve ruff errors in tests and run_tests.py
- Fix import sorting (I001) - Remove unused imports and variables (F401, F841) - Add noqa for test code (S106 hardcoded passwords, S314 XML parsing) - Auto-format with ruff format
This commit is contained in:
@@ -17,6 +17,12 @@
|
|||||||
- `docker/build-push-action@v5` → чистые `docker build/push` команды
|
- `docker/build-push-action@v5` → чистые `docker build/push` команды
|
||||||
- Тесты используют `config.settings.test` (SQLite in-memory) вместо PostgreSQL service
|
- Тесты используют `config.settings.test` (SQLite in-memory) вместо PostgreSQL service
|
||||||
|
|
||||||
|
#### Code Quality
|
||||||
|
- Исправлены ошибки ruff lint:
|
||||||
|
- Сортировка импортов (I001)
|
||||||
|
- Удалены неиспользуемые импорты и переменные (F401, F841)
|
||||||
|
- Добавлены noqa для тестового кода (S106, S314)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## [0.4.0] - 2026-01-28
|
## [0.4.0] - 2026-01-28
|
||||||
|
|||||||
35
run_tests.py
35
run_tests.py
@@ -5,10 +5,9 @@
|
|||||||
Поддерживает coverage и дополнительные опции
|
Поддерживает coverage и дополнительные опции
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from io import StringIO
|
|
||||||
import argparse
|
|
||||||
|
|
||||||
import django
|
import django
|
||||||
|
|
||||||
@@ -59,51 +58,47 @@ def run_tests_with_args(test_args, options):
|
|||||||
|
|
||||||
def parse_arguments():
|
def parse_arguments():
|
||||||
"""Парсинг аргументов командной строки"""
|
"""Парсинг аргументов командной строки"""
|
||||||
parser = argparse.ArgumentParser(description="Запуск Django тестов с дополнительными возможностями")
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Запуск Django тестов с дополнительными возможностями"
|
||||||
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"targets",
|
"targets",
|
||||||
nargs="*",
|
nargs="*",
|
||||||
help="Цели тестирования (по умолчанию: все тесты)",
|
help="Цели тестирования (по умолчанию: все тесты)",
|
||||||
default=["tests"]
|
default=["tests"],
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--coverage", "--cov",
|
"--coverage",
|
||||||
|
"--cov",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="Запуск тестов с измерением покрытия кода"
|
help="Запуск тестов с измерением покрытия кода",
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--fast",
|
"--fast",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="Запуск только быстрых тестов (исключает медленные)"
|
help="Запуск только быстрых тестов (исключает медленные)",
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--failfast",
|
"--failfast", action="store_true", help="Остановка при первой ошибке"
|
||||||
action="store_true",
|
|
||||||
help="Остановка при первой ошибке"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--verbose", "-v",
|
"--verbose", "-v", action="count", default=2, help="Уровень детализации вывода"
|
||||||
action="count",
|
|
||||||
default=2,
|
|
||||||
help="Уровень детализации вывода"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--keepdb",
|
"--keepdb", action="store_true", help="Сохранить тестовую базу данных"
|
||||||
action="store_true",
|
|
||||||
help="Сохранить тестовую базу данных"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--parallel",
|
"--parallel",
|
||||||
type=int,
|
type=int,
|
||||||
metavar="N",
|
metavar="N",
|
||||||
help="Запуск тестов в N параллельных процессах"
|
help="Запуск тестов в N параллельных процессах",
|
||||||
)
|
)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
@@ -186,6 +181,7 @@ def setup_coverage():
|
|||||||
"""Настройка coverage"""
|
"""Настройка coverage"""
|
||||||
try:
|
try:
|
||||||
import coverage
|
import coverage
|
||||||
|
|
||||||
cov = coverage.Coverage(config_file="pyproject.toml")
|
cov = coverage.Coverage(config_file="pyproject.toml")
|
||||||
cov.start()
|
cov.start()
|
||||||
return cov
|
return cov
|
||||||
@@ -245,7 +241,7 @@ def main():
|
|||||||
print(f"\n❌ Тесты завершились с ошибками: {failures} неудачных тестов")
|
print(f"\n❌ Тесты завершились с ошибками: {failures} неудачных тестов")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
else:
|
else:
|
||||||
print(f"\n✅ Все тесты прошли успешно!")
|
print("\n✅ Все тесты прошли успешно!")
|
||||||
if cov:
|
if cov:
|
||||||
print("📊 Отчет о покрытии сохранен")
|
print("📊 Отчет о покрытии сохранен")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
@@ -260,6 +256,7 @@ def main():
|
|||||||
if cov:
|
if cov:
|
||||||
cov.stop()
|
cov.stop()
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ class BackgroundJobServiceTest(TestCase):
|
|||||||
def test_get_user_jobs_with_status_filter(self):
|
def test_get_user_jobs_with_status_filter(self):
|
||||||
"""Тест фильтрации по статусу."""
|
"""Тест фильтрации по статусу."""
|
||||||
user_id = 456
|
user_id = 456
|
||||||
job1 = BackgroundJobService.create_job(
|
BackgroundJobService.create_job(
|
||||||
task_id="task-pending",
|
task_id="task-pending",
|
||||||
task_name="test.task",
|
task_name="test.task",
|
||||||
user_id=user_id,
|
user_id=user_id,
|
||||||
@@ -212,7 +212,7 @@ class BackgroundJobServiceTest(TestCase):
|
|||||||
def test_get_active_jobs(self):
|
def test_get_active_jobs(self):
|
||||||
"""Тест получения активных задач."""
|
"""Тест получения активных задач."""
|
||||||
# Создаём задачи с разными статусами
|
# Создаём задачи с разными статусами
|
||||||
job_pending = BackgroundJobService.create_job(
|
BackgroundJobService.create_job(
|
||||||
task_id="job-active-pending",
|
task_id="job-active-pending",
|
||||||
task_name="test.task",
|
task_name="test.task",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ class BulkOperationsIntegrationTest(TestCase):
|
|||||||
|
|
||||||
def test_bulk_create_chunked(self):
|
def test_bulk_create_chunked(self):
|
||||||
"""Тест массового создания чанками."""
|
"""Тест массового создания чанками."""
|
||||||
|
|
||||||
# Создаём тестовый сервис с BulkOperationsMixin
|
# Создаём тестовый сервис с BulkOperationsMixin
|
||||||
class TestService(BulkOperationsMixin):
|
class TestService(BulkOperationsMixin):
|
||||||
model = BackgroundJob
|
model = BackgroundJob
|
||||||
@@ -88,10 +89,13 @@ class BulkOperationsIntegrationTest(TestCase):
|
|||||||
self.assertEqual(count, 10)
|
self.assertEqual(count, 10)
|
||||||
|
|
||||||
# Проверяем что все созданы
|
# Проверяем что все созданы
|
||||||
self.assertEqual(BackgroundJob.objects.filter(task_name="test.bulk.task").count(), 10)
|
self.assertEqual(
|
||||||
|
BackgroundJob.objects.filter(task_name="test.bulk.task").count(), 10
|
||||||
|
)
|
||||||
|
|
||||||
def test_bulk_delete(self):
|
def test_bulk_delete(self):
|
||||||
"""Тест массового удаления."""
|
"""Тест массового удаления."""
|
||||||
|
|
||||||
class TestService(BulkOperationsMixin):
|
class TestService(BulkOperationsMixin):
|
||||||
model = BackgroundJob
|
model = BackgroundJob
|
||||||
|
|
||||||
@@ -109,10 +113,13 @@ class BulkOperationsIntegrationTest(TestCase):
|
|||||||
deleted = TestService.bulk_delete(ids_to_delete)
|
deleted = TestService.bulk_delete(ids_to_delete)
|
||||||
|
|
||||||
self.assertEqual(deleted, 3)
|
self.assertEqual(deleted, 3)
|
||||||
self.assertEqual(BackgroundJob.objects.filter(task_name="test.delete.task").count(), 2)
|
self.assertEqual(
|
||||||
|
BackgroundJob.objects.filter(task_name="test.delete.task").count(), 2
|
||||||
|
)
|
||||||
|
|
||||||
def test_bulk_update_fields(self):
|
def test_bulk_update_fields(self):
|
||||||
"""Тест массового обновления полей."""
|
"""Тест массового обновления полей."""
|
||||||
|
|
||||||
class TestService(BulkOperationsMixin):
|
class TestService(BulkOperationsMixin):
|
||||||
model = BackgroundJob
|
model = BackgroundJob
|
||||||
|
|
||||||
@@ -138,6 +145,7 @@ class BulkOperationsIntegrationTest(TestCase):
|
|||||||
|
|
||||||
def test_bulk_update_or_create_creates(self):
|
def test_bulk_update_or_create_creates(self):
|
||||||
"""Тест upsert - создание новых."""
|
"""Тест upsert - создание новых."""
|
||||||
|
|
||||||
class TestService(BulkOperationsMixin):
|
class TestService(BulkOperationsMixin):
|
||||||
model = BackgroundJob
|
model = BackgroundJob
|
||||||
|
|
||||||
@@ -157,6 +165,7 @@ class BulkOperationsIntegrationTest(TestCase):
|
|||||||
|
|
||||||
def test_bulk_update_or_create_updates(self):
|
def test_bulk_update_or_create_updates(self):
|
||||||
"""Тест upsert - обновление существующих."""
|
"""Тест upsert - обновление существующих."""
|
||||||
|
|
||||||
class TestService(BulkOperationsMixin):
|
class TestService(BulkOperationsMixin):
|
||||||
model = BackgroundJob
|
model = BackgroundJob
|
||||||
|
|
||||||
|
|||||||
@@ -101,9 +101,7 @@ class APIPaginatedResponseTest(TestCase):
|
|||||||
def test_paginated_response(self):
|
def test_paginated_response(self):
|
||||||
"""Test paginated response with correct metadata"""
|
"""Test paginated response with correct metadata"""
|
||||||
data = [{"id": 1}, {"id": 2}]
|
data = [{"id": 1}, {"id": 2}]
|
||||||
response = api_paginated_response(
|
response = api_paginated_response(data, page=1, page_size=10, total_count=25)
|
||||||
data, page=1, page_size=10, total_count=25
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
self.assertEqual(response.data["data"], data)
|
self.assertEqual(response.data["data"], data)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class BaseServiceTest(TestCase):
|
|||||||
self.user = User.objects.create_user(
|
self.user = User.objects.create_user(
|
||||||
username="testuser",
|
username="testuser",
|
||||||
email="test@example.com",
|
email="test@example.com",
|
||||||
password="testpass123",
|
password="testpass123", # noqa: S106
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_get_by_id_success(self):
|
def test_get_by_id_success(self):
|
||||||
@@ -53,7 +53,7 @@ class BaseServiceTest(TestCase):
|
|||||||
User.objects.create_user(
|
User.objects.create_user(
|
||||||
username="testuser2",
|
username="testuser2",
|
||||||
email="test2@example.com",
|
email="test2@example.com",
|
||||||
password="testpass123",
|
password="testpass123", # noqa: S106
|
||||||
)
|
)
|
||||||
|
|
||||||
result = UserTestService.get_all()
|
result = UserTestService.get_all()
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ class SignalDispatcherTest(TestCase):
|
|||||||
self.dispatcher.connect_all()
|
self.dispatcher.connect_all()
|
||||||
|
|
||||||
# Create user to trigger signal
|
# Create user to trigger signal
|
||||||
user = UserFactory.create_user()
|
UserFactory.create_user()
|
||||||
|
|
||||||
self.assertTrue(handler_called["value"])
|
self.assertTrue(handler_called["value"])
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ class SignalDispatcherTest(TestCase):
|
|||||||
|
|
||||||
# Create user - handler should not be called
|
# Create user - handler should not be called
|
||||||
handler_called["value"] = False
|
handler_called["value"] = False
|
||||||
user = UserFactory.create_user()
|
UserFactory.create_user()
|
||||||
|
|
||||||
self.assertFalse(handler_called["value"])
|
self.assertFalse(handler_called["value"])
|
||||||
|
|
||||||
|
|||||||
@@ -3,10 +3,7 @@
|
|||||||
import random
|
import random
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from django.utils import timezone
|
|
||||||
|
|
||||||
import factory
|
import factory
|
||||||
|
|
||||||
from apps.parsers.models import (
|
from apps.parsers.models import (
|
||||||
IndustrialCertificateRecord,
|
IndustrialCertificateRecord,
|
||||||
InspectionRecord,
|
InspectionRecord,
|
||||||
@@ -14,6 +11,7 @@ from apps.parsers.models import (
|
|||||||
ParserLoadLog,
|
ParserLoadLog,
|
||||||
Proxy,
|
Proxy,
|
||||||
)
|
)
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
# === Хелперы для генерации реалистичных данных ===
|
# === Хелперы для генерации реалистичных данных ===
|
||||||
|
|
||||||
@@ -320,7 +318,9 @@ class InspectionRecordFactory(factory.django.DjangoModelFactory):
|
|||||||
lambda _: random.choice(["плановая", "внеплановая"])
|
lambda _: random.choice(["плановая", "внеплановая"])
|
||||||
)
|
)
|
||||||
inspection_form = factory.LazyAttribute(
|
inspection_form = factory.LazyAttribute(
|
||||||
lambda _: random.choice(["документарная", "выездная", "документарная и выездная"])
|
lambda _: random.choice(
|
||||||
|
["документарная", "выездная", "документарная и выездная"]
|
||||||
|
)
|
||||||
)
|
)
|
||||||
start_date = factory.LazyAttribute(
|
start_date = factory.LazyAttribute(
|
||||||
lambda _: (timezone.now() - timedelta(days=random.randint(1, 180))).strftime(
|
lambda _: (timezone.now() - timedelta(days=random.randint(1, 180))).strftime(
|
||||||
@@ -339,9 +339,7 @@ class InspectionRecordFactory(factory.django.DjangoModelFactory):
|
|||||||
lambda _: random.choice(["294-ФЗ", "248-ФЗ", "184-ФЗ"])
|
lambda _: random.choice(["294-ФЗ", "248-ФЗ", "184-ФЗ"])
|
||||||
)
|
)
|
||||||
result = factory.LazyAttribute(
|
result = factory.LazyAttribute(
|
||||||
lambda _: random.choice(
|
lambda _: random.choice(["нарушения не выявлены", "выявлены нарушения", ""])
|
||||||
["нарушения не выявлены", "выявлены нарушения", ""]
|
|
||||||
)
|
|
||||||
if random.random() > 0.3
|
if random.random() > 0.3
|
||||||
else ""
|
else ""
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,17 +3,15 @@
|
|||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from django.test import TestCase, tag
|
|
||||||
|
|
||||||
from faker import Faker
|
|
||||||
from openpyxl import Workbook
|
|
||||||
|
|
||||||
from apps.parsers.clients.base import BaseHTTPClient, HTTPClientError
|
from apps.parsers.clients.base import BaseHTTPClient, HTTPClientError
|
||||||
from apps.parsers.clients.minpromtorg.industrial import IndustrialProductionClient
|
from apps.parsers.clients.minpromtorg.industrial import IndustrialProductionClient
|
||||||
from apps.parsers.clients.minpromtorg.manufactures import ManufacturesClient
|
from apps.parsers.clients.minpromtorg.manufactures import ManufacturesClient
|
||||||
from apps.parsers.clients.minpromtorg.schemas import IndustrialCertificate, Manufacturer
|
from apps.parsers.clients.minpromtorg.schemas import IndustrialCertificate, Manufacturer
|
||||||
from apps.parsers.clients.proverki import ProverkiClient
|
from apps.parsers.clients.proverki import ProverkiClient
|
||||||
from apps.parsers.clients.proverki.schemas import Inspection
|
from apps.parsers.clients.proverki.schemas import Inspection
|
||||||
|
from django.test import TestCase, tag
|
||||||
|
from faker import Faker
|
||||||
|
from openpyxl import Workbook
|
||||||
|
|
||||||
fake = Faker("ru_RU")
|
fake = Faker("ru_RU")
|
||||||
|
|
||||||
@@ -159,7 +157,10 @@ class IndustrialProductionClientTest(TestCase):
|
|||||||
{
|
{
|
||||||
"name": "Заключения о подтверждении производства промышленной продукции на территории Российской Федерации",
|
"name": "Заключения о подтверждении производства промышленной продукции на территории Российской Федерации",
|
||||||
"files": [
|
"files": [
|
||||||
{"name": "data_resolutions_20240101.xlsx", "url": "/files/test.xlsx"},
|
{
|
||||||
|
"name": "data_resolutions_20240101.xlsx",
|
||||||
|
"url": "/files/test.xlsx",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -193,9 +194,18 @@ class IndustrialProductionClientTest(TestCase):
|
|||||||
{
|
{
|
||||||
"name": "Заключения о подтверждении производства промышленной продукции на территории Российской Федерации",
|
"name": "Заключения о подтверждении производства промышленной продукции на территории Российской Федерации",
|
||||||
"files": [
|
"files": [
|
||||||
{"name": "data_resolutions_20240101.xlsx", "url": "/files/old.xlsx"},
|
{
|
||||||
{"name": "data_resolutions_20240315.xlsx", "url": "/files/new.xlsx"},
|
"name": "data_resolutions_20240101.xlsx",
|
||||||
{"name": "data_resolutions_20240201.xlsx", "url": "/files/mid.xlsx"},
|
"url": "/files/old.xlsx",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "data_resolutions_20240315.xlsx",
|
||||||
|
"url": "/files/new.xlsx",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "data_resolutions_20240201.xlsx",
|
||||||
|
"url": "/files/mid.xlsx",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -539,7 +549,7 @@ class ProverkiClientTest(TestCase):
|
|||||||
|
|
||||||
client = ProverkiClient()
|
client = ProverkiClient()
|
||||||
xml_str = '<inspection inn="1234567890" registration_number="TEST123" organisation_name="Test Co"/>'
|
xml_str = '<inspection inn="1234567890" registration_number="TEST123" organisation_name="Test Co"/>'
|
||||||
element = ET.fromstring(xml_str)
|
element = ET.fromstring(xml_str) # noqa: S314
|
||||||
|
|
||||||
result = client._parse_xml_record(element)
|
result = client._parse_xml_record(element)
|
||||||
|
|
||||||
@@ -553,7 +563,7 @@ class ProverkiClientTest(TestCase):
|
|||||||
|
|
||||||
client = ProverkiClient()
|
client = ProverkiClient()
|
||||||
xml_str = "<empty_record></empty_record>"
|
xml_str = "<empty_record></empty_record>"
|
||||||
element = ET.fromstring(xml_str)
|
element = ET.fromstring(xml_str) # noqa: S314
|
||||||
|
|
||||||
result = client._parse_xml_record(element)
|
result = client._parse_xml_record(element)
|
||||||
|
|
||||||
@@ -569,9 +579,7 @@ class ProverkiClientTest(TestCase):
|
|||||||
<registration_number>TEST001</registration_number>
|
<registration_number>TEST001</registration_number>
|
||||||
<organisation_name>Компания</organisation_name>
|
<organisation_name>Компания</organisation_name>
|
||||||
</inspection>
|
</inspection>
|
||||||
</inspections>""".encode(
|
</inspections>""".encode("windows-1251")
|
||||||
"windows-1251"
|
|
||||||
)
|
|
||||||
|
|
||||||
inspections = client._parse_xml_content(xml_content, None)
|
inspections = client._parse_xml_content(xml_content, None)
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
"""Tests for parsers models."""
|
"""Tests for parsers models."""
|
||||||
|
|
||||||
from django.test import TestCase
|
|
||||||
|
|
||||||
from apps.parsers.models import (
|
from apps.parsers.models import (
|
||||||
IndustrialCertificateRecord,
|
IndustrialCertificateRecord,
|
||||||
ManufacturerRecord,
|
ManufacturerRecord,
|
||||||
ParserLoadLog,
|
ParserLoadLog,
|
||||||
Proxy,
|
Proxy,
|
||||||
)
|
)
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
from .factories import (
|
from .factories import (
|
||||||
IndustrialCertificateRecordFactory,
|
IndustrialCertificateRecordFactory,
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
"""Tests for parsers services."""
|
"""Tests for parsers services."""
|
||||||
|
|
||||||
from django.test import TestCase
|
|
||||||
|
|
||||||
from faker import Faker
|
|
||||||
|
|
||||||
from apps.parsers.clients.minpromtorg.schemas import IndustrialCertificate, Manufacturer
|
from apps.parsers.clients.minpromtorg.schemas import IndustrialCertificate, Manufacturer
|
||||||
from apps.parsers.clients.proverki.schemas import Inspection
|
from apps.parsers.clients.proverki.schemas import Inspection
|
||||||
from apps.parsers.models import (
|
from apps.parsers.models import (
|
||||||
@@ -20,6 +16,8 @@ from apps.parsers.services import (
|
|||||||
ParserLoadLogService,
|
ParserLoadLogService,
|
||||||
ProxyService,
|
ProxyService,
|
||||||
)
|
)
|
||||||
|
from django.test import TestCase
|
||||||
|
from faker import Faker
|
||||||
|
|
||||||
from .factories import (
|
from .factories import (
|
||||||
IndustrialCertificateRecordFactory,
|
IndustrialCertificateRecordFactory,
|
||||||
@@ -147,7 +145,9 @@ class ParserLoadLogServiceTest(TestCase):
|
|||||||
|
|
||||||
def test_get_next_batch_id_first(self):
|
def test_get_next_batch_id_first(self):
|
||||||
"""Test getting first batch_id for new source."""
|
"""Test getting first batch_id for new source."""
|
||||||
batch_id = ParserLoadLogService.get_next_batch_id(ParserLoadLog.Source.INDUSTRIAL)
|
batch_id = ParserLoadLogService.get_next_batch_id(
|
||||||
|
ParserLoadLog.Source.INDUSTRIAL
|
||||||
|
)
|
||||||
self.assertEqual(batch_id, 1)
|
self.assertEqual(batch_id, 1)
|
||||||
|
|
||||||
def test_get_next_batch_id_increment(self):
|
def test_get_next_batch_id_increment(self):
|
||||||
@@ -155,7 +155,9 @@ class ParserLoadLogServiceTest(TestCase):
|
|||||||
ParserLoadLogFactory(batch_id=5, source=ParserLoadLog.Source.INDUSTRIAL)
|
ParserLoadLogFactory(batch_id=5, source=ParserLoadLog.Source.INDUSTRIAL)
|
||||||
ParserLoadLogFactory(batch_id=3, source=ParserLoadLog.Source.INDUSTRIAL)
|
ParserLoadLogFactory(batch_id=3, source=ParserLoadLog.Source.INDUSTRIAL)
|
||||||
|
|
||||||
batch_id = ParserLoadLogService.get_next_batch_id(ParserLoadLog.Source.INDUSTRIAL)
|
batch_id = ParserLoadLogService.get_next_batch_id(
|
||||||
|
ParserLoadLog.Source.INDUSTRIAL
|
||||||
|
)
|
||||||
self.assertEqual(batch_id, 6)
|
self.assertEqual(batch_id, 6)
|
||||||
|
|
||||||
def test_get_next_batch_id_per_source(self):
|
def test_get_next_batch_id_per_source(self):
|
||||||
@@ -272,7 +274,9 @@ class IndustrialCertificateServiceTest(TestCase):
|
|||||||
results = IndustrialCertificateService.find_by_inn("1111111111")
|
results = IndustrialCertificateService.find_by_inn("1111111111")
|
||||||
self.assertEqual(results.count(), 2)
|
self.assertEqual(results.count(), 2)
|
||||||
|
|
||||||
results_batch1 = IndustrialCertificateService.find_by_inn("1111111111", batch_id=1)
|
results_batch1 = IndustrialCertificateService.find_by_inn(
|
||||||
|
"1111111111", batch_id=1
|
||||||
|
)
|
||||||
self.assertEqual(results_batch1.count(), 1)
|
self.assertEqual(results_batch1.count(), 1)
|
||||||
|
|
||||||
def test_find_by_certificate_number(self):
|
def test_find_by_certificate_number(self):
|
||||||
@@ -313,7 +317,7 @@ class IndustrialCertificateServiceTest(TestCase):
|
|||||||
ogrn="9999999999999",
|
ogrn="9999999999999",
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
count2 = IndustrialCertificateService.save_certificates(duplicate, batch_id=2)
|
IndustrialCertificateService.save_certificates(duplicate, batch_id=2)
|
||||||
|
|
||||||
# Should still be 1 record (duplicate skipped)
|
# Should still be 1 record (duplicate skipped)
|
||||||
self.assertEqual(IndustrialCertificateRecord.objects.count(), 1)
|
self.assertEqual(IndustrialCertificateRecord.objects.count(), 1)
|
||||||
@@ -420,7 +424,7 @@ class ManufacturerServiceTest(TestCase):
|
|||||||
address="New Address",
|
address="New Address",
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
count2 = ManufacturerService.save_manufacturers(duplicate, batch_id=2)
|
ManufacturerService.save_manufacturers(duplicate, batch_id=2)
|
||||||
|
|
||||||
# Should still be 1 record (duplicate skipped)
|
# Should still be 1 record (duplicate skipped)
|
||||||
self.assertEqual(ManufacturerRecord.objects.count(), 1)
|
self.assertEqual(ManufacturerRecord.objects.count(), 1)
|
||||||
@@ -567,7 +571,7 @@ class InspectionServiceTest(TestCase):
|
|||||||
result="выявлены нарушения",
|
result="выявлены нарушения",
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
count2 = InspectionService.save_inspections(duplicate, batch_id=2)
|
InspectionService.save_inspections(duplicate, batch_id=2)
|
||||||
|
|
||||||
# Should still be 1 record (duplicate skipped)
|
# Should still be 1 record (duplicate skipped)
|
||||||
self.assertEqual(InspectionRecord.objects.count(), 1)
|
self.assertEqual(InspectionRecord.objects.count(), 1)
|
||||||
@@ -581,10 +585,9 @@ class InspectionServiceTest(TestCase):
|
|||||||
self.assertEqual(record.load_batch, 1) # Original batch
|
self.assertEqual(record.load_batch, 1) # Original batch
|
||||||
|
|
||||||
|
|
||||||
from django.test import tag
|
|
||||||
|
|
||||||
from apps.parsers.clients.base import HTTPClientError
|
from apps.parsers.clients.base import HTTPClientError
|
||||||
from apps.parsers.clients.minpromtorg.industrial import IndustrialProductionClient
|
from apps.parsers.clients.minpromtorg.industrial import IndustrialProductionClient
|
||||||
|
from django.test import tag
|
||||||
|
|
||||||
|
|
||||||
@tag("integration", "slow", "network", "e2e")
|
@tag("integration", "slow", "network", "e2e")
|
||||||
@@ -674,4 +677,3 @@ class EndToEndIntegrationTest(TestCase):
|
|||||||
|
|
||||||
except HTTPClientError as e:
|
except HTTPClientError as e:
|
||||||
self.skipTest(f"External API unavailable: {e}")
|
self.skipTest(f"External API unavailable: {e}")
|
||||||
|
|
||||||
|
|||||||
@@ -16,9 +16,7 @@ class UserFactory(factory.django.DjangoModelFactory):
|
|||||||
|
|
||||||
email = factory.LazyAttribute(lambda _: fake.unique.email())
|
email = factory.LazyAttribute(lambda _: fake.unique.email())
|
||||||
username = factory.LazyAttribute(lambda _: fake.unique.user_name())
|
username = factory.LazyAttribute(lambda _: fake.unique.user_name())
|
||||||
phone = factory.LazyAttribute(
|
phone = factory.LazyAttribute(lambda _: f"+7{fake.numerify('##########')}")
|
||||||
lambda _: f"+7{fake.numerify('##########')}"
|
|
||||||
)
|
|
||||||
is_verified = False
|
is_verified = False
|
||||||
is_staff = False
|
is_staff = False
|
||||||
is_superuser = False
|
is_superuser = False
|
||||||
@@ -58,7 +56,9 @@ class ProfileFactory(factory.django.DjangoModelFactory):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Profile
|
model = Profile
|
||||||
django_get_or_create = ("user",) # Используем get_or_create для избежания дубликатов
|
django_get_or_create = (
|
||||||
|
"user",
|
||||||
|
) # Используем get_or_create для избежания дубликатов
|
||||||
|
|
||||||
user = factory.SubFactory(UserFactory)
|
user = factory.SubFactory(UserFactory)
|
||||||
first_name = factory.LazyAttribute(lambda _: fake.first_name())
|
first_name = factory.LazyAttribute(lambda _: fake.first_name())
|
||||||
|
|||||||
Reference in New Issue
Block a user