Files
kadastr14/tests.py
2025-08-12 23:53:44 +05:00

251 lines
12 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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()