#!/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()