This commit is contained in:
2025-08-12 23:53:44 +05:00
parent a882a81180
commit 6af7d54070
13 changed files with 462 additions and 431 deletions

250
tests.py Normal file
View File

@@ -0,0 +1,250 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Объединенный класс тестов для проекта KadastrParser
"""
import os
import tempfile
from pathlib import Path
import unittest
from typing import Optional
# Импорт наших модулей
from models.cadastral_record import CadastralRecord
from models.xml_file_info import XMLFileInfo
from services.file_seeker import FileSeeker
from services.excel_processor import ExcelProcessor
class KadastrParserTests(unittest.TestCase):
"""Объединенный класс тестов для всех компонентов системы"""
@classmethod
def setUpClass(cls):
"""Настройка тестовой среды"""
cls.test_xml_dir = r"c:\Users\USER\Downloads\14. выборка выписок из ЕГРН по списку КН\пример исх.папки 2 вар"
cls.test_excel_file = r"c:\Users\USER\Downloads\14. выборка выписок из ЕГРН по списку КН\список КН.xlsx"
cls.test_xml_file = r"c:\Users\USER\Downloads\14. выборка выписок из ЕГРН по списку КН\пример исх.папки 2 вар\report-1a3f8d46-0b14-4ae3-ac2e-f10372020fed-PKPVD-2025-05-12-224487-74-01[0].xml"
# Создаем временную директорию для результатов
cls.temp_dir = Path("test_results")
cls.temp_dir.mkdir(exist_ok=True)
def test_01_module_imports(self):
"""Тестирует импорт и создание всех модулей"""
print("\n=== ТЕСТ 1: ИМПОРТ МОДУЛЕЙ ===")
# Тест создания CadastralRecord
record = CadastralRecord("74:34:0400003:1234", "test.xml", {"74:34:0400003:1234", "74:34:0400003:5678"})
self.assertEqual(record.main_number, "74:34:0400003:1234")
self.assertEqual(record.file_path, "test.xml")
self.assertEqual(len(record.all_numbers), 2)
self.assertEqual(len(record.other_numbers), 1)
print(f" ✅ CadastralRecord: {record}")
# Тест создания FileSeeker
temp_dir = tempfile.mkdtemp()
seeker = FileSeeker(temp_dir)
stats = seeker.get_statistics()
self.assertIsInstance(stats, dict)
print(f" ✅ FileSeeker создан: {seeker}")
# Тест создания ExcelProcessor
excel_processor = ExcelProcessor("dummy.xlsx")
self.assertIsInstance(excel_processor, ExcelProcessor)
print(f" ✅ ExcelProcessor создан")
def test_02_single_xml_file_extraction(self):
"""Тестирует извлечение из одного XML файла"""
print("\n=== ТЕСТ 2: ИЗВЛЕЧЕНИЕ ИЗ XML ФАЙЛА ===")
if not os.path.exists(self.test_xml_file):
self.skipTest(f"Тестовый файл не найден: {self.test_xml_file}")
xml_info = XMLFileInfo(self.test_xml_file)
main_number, all_numbers = xml_info.extract_cadastral_data()
self.assertIsNotNone(main_number)
self.assertGreater(len(all_numbers), 0)
self.assertIn(main_number, all_numbers)
print(f" 📋 Основной номер: {main_number}")
print(f" 📋 Всего номеров: {len(all_numbers)}")
print(f" 📋 Номера: {sorted(all_numbers)}")
def test_03_directory_processing(self):
"""Тестирует обработку директории с XML файлами"""
print("\n=== ТЕСТ 3: ОБРАБОТКА ДИРЕКТОРИИ ===")
if not os.path.exists(self.test_xml_dir):
self.skipTest(f"Тестовая директория не найдена: {self.test_xml_dir}")
seeker = FileSeeker(self.test_xml_dir, str(self.temp_dir))
# Поиск файлов
xml_files = seeker.find_xml_files()
self.assertGreater(len(xml_files), 0)
print(f" 📁 Найдено XML файлов: {len(xml_files)}")
# Обработка файлов (новая реализация с объектами)
records = seeker.process_files()
self.assertGreater(len(records), 0)
print(f" 📋 Создано объектов: {len(records)}")
# Проверяем статистику
stats = seeker.get_statistics()
self.assertEqual(stats['total_xml_files'], len(xml_files))
self.assertEqual(stats['total_cadastral_objects'], len(records))
print(f" 📊 Статистика:")
for key, value in stats.items():
print(f"{key}: {value}")
# Проверяем первые несколько записей
print(f" 📋 Первые 3 объекта:")
for i, record in enumerate(records[:3]):
print(f" {i+1}. Основной: {record.main_number}")
print(f" Все номера: {sorted(record.all_numbers)}")
print(f" Других номеров: {len(record.other_numbers)}")
def test_04_excel_processing(self):
"""Тестирует обработку Excel файла"""
print("\n=== ТЕСТ 4: ОБРАБОТКА EXCEL ===")
if not os.path.exists(self.test_excel_file):
self.skipTest(f"Excel файл не найден: {self.test_excel_file}")
excel_processor = ExcelProcessor(self.test_excel_file)
success = excel_processor.load_excel_file()
self.assertTrue(success)
excel_numbers = excel_processor.get_cadastral_numbers()
self.assertGreater(len(excel_numbers), 0)
print(f" 📊 Номеров в Excel: {len(excel_numbers)}")
# Показываем первые 5 номеров
print(f" 📋 Первые 5 номеров из Excel:")
for i, number in enumerate(sorted(excel_numbers)[:5]):
print(f" {i+1}. {number}")
def test_05_full_integration(self):
"""Полный интеграционный тест XML + Excel + обновление"""
print("\n=== ТЕСТ 5: ПОЛНАЯ ИНТЕГРАЦИЯ ===")
if not os.path.exists(self.test_xml_dir) or not os.path.exists(self.test_excel_file):
self.skipTest("Тестовые файлы не найдены для интеграционного теста")
# 1. Обработка XML файлов
seeker = FileSeeker(self.test_xml_dir, str(self.temp_dir))
xml_files = seeker.find_xml_files()
records = seeker.process_files()
# 2. Обработка Excel файла
excel_processor = ExcelProcessor(self.test_excel_file)
excel_processor.load_excel_file()
excel_numbers = excel_processor.get_cadastral_numbers()
# 3. Поиск совпадений (по всем номерам в объектах)
all_xml_numbers = seeker.get_all_cadastral_numbers()
matching_numbers = excel_numbers.intersection(all_xml_numbers)
print(f" 🏷️ XML номеров (всего): {len(all_xml_numbers)}")
print(f" 📊 Excel номеров: {len(excel_numbers)}")
print(f" 🎯 Совпадений: {len(matching_numbers)}")
self.assertGreater(len(matching_numbers), 0, "Должны быть найдены совпадения")
# 4. Тестируем новый метод обновления Excel с объектами
output_excel = str(self.temp_dir / "integration_test_updated.xlsx")
success = excel_processor.update_excel_with_cadastral_records(records, output_excel)
self.assertTrue(success, "Обновление Excel должно быть успешным")
print(f" ✅ Excel обновлен: {Path(output_excel).name}")
# Проверяем созданный файл
self.assertTrue(os.path.exists(output_excel))
# Показываем первые совпадения
if matching_numbers:
print(f" 🎯 Первые 5 совпадений:")
for i, number in enumerate(sorted(matching_numbers)[:5]):
print(f" {i+1}. {number}")
def test_06_new_implementation_features(self):
"""Тестирует особенности новой реализации с объектами"""
print("\n=== ТЕСТ 6: НОВАЯ РЕАЛИЗАЦИЯ ===")
if not os.path.exists(self.test_xml_dir):
self.skipTest("Тестовая директория не найдена")
seeker = FileSeeker(self.test_xml_dir)
records = seeker.process_files()
# Проверяем, что каждая запись - это объект с множественными номерами
objects_with_multiple_numbers = [r for r in records if len(r.all_numbers) > 1]
print(f" 📋 Всего объектов: {len(records)}")
print(f" 🔗 Объектов с несколькими номерами: {len(objects_with_multiple_numbers)}")
# Показываем примеры объектов с несколькими номерами
if objects_with_multiple_numbers:
print(f" 📋 Примеры объектов с несколькими номерами:")
for i, record in enumerate(objects_with_multiple_numbers[:3]):
print(f" {i+1}. Основной: {record.main_number}")
print(f" Всего номеров: {len(record.all_numbers)}")
print(f" Другие номера: {sorted(record.other_numbers)}")
# Проверяем уникальность основных номеров
main_numbers = [r.main_number for r in records]
unique_main_numbers = set(main_numbers)
print(f" 🏷️ Уникальных основных номеров: {len(unique_main_numbers)}")
print(f" 📊 Всего номеров во всех объектах: {sum(len(r.all_numbers) for r in records)}")
@classmethod
def tearDownClass(cls):
"""Очистка после тестов"""
print("\n=== ОЧИСТКА ===")
# Можно добавить очистку временных файлов если нужно
pass
def run_all_tests():
"""Запускает все тесты с подробным выводом"""
print("🚀 ЗАПУСК ОБЪЕДИНЕННЫХ ТЕСТОВ KADASTR PARSER")
print("=" * 60)
# Создаем тестовый набор
loader = unittest.TestLoader()
suite = loader.loadTestsFromTestCase(KadastrParserTests)
# Запускаем тесты с подробным выводом
runner = unittest.TextTestRunner(verbosity=2, stream=None)
result = runner.run(suite)
print("\n" + "=" * 60)
print("🎯 ИТОГОВЫЕ РЕЗУЛЬТАТЫ:")
print(f" ✅ Успешных тестов: {result.testsRun - len(result.failures) - len(result.errors)}")
print(f" ❌ Неудачных тестов: {len(result.failures)}")
print(f" 💥 Ошибок: {len(result.errors)}")
print(f" ⏭️ Пропущенных: {len(result.skipped)}")
if result.failures:
print("\n❌ НЕУДАЧИ:")
for test, error in result.failures:
print(f"{test}: {error}")
if result.errors:
print("\n💥 ОШИБКИ:")
for test, error in result.errors:
print(f"{test}: {error}")
success = len(result.failures) == 0 and len(result.errors) == 0
print(f"\n🏆 ОБЩИЙ РЕЗУЛЬТАТ: {'ВСЕ ТЕСТЫ ПРОШЛИ' if success else 'ЕСТЬ ПРОБЛЕМЫ'}")
return success
if __name__ == "__main__":
run_all_tests()