Улучшение отчета для rack_coverage
This commit is contained in:
@@ -12,19 +12,20 @@ import ast
|
||||
import configparser
|
||||
import fnmatch
|
||||
import importlib
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.management import CommandError
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from net.xeaf.rack.core import CoreCommand
|
||||
from .coverage_structure_visitor import CoverageStructureVisitor
|
||||
from .coverage_test_file_visitor import CoverageTestFileVisitor
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
class Command(CoreCommand):
|
||||
"""
|
||||
Проверяет соблюдение принципа один метод - один файл тестов
|
||||
"""
|
||||
@@ -39,6 +40,18 @@ class Command(BaseCommand):
|
||||
help = "Discover test coverage in the specified modules or the current directory."
|
||||
""" Подсказка """
|
||||
|
||||
success_count: int = 0
|
||||
""" Счетчик успешно проверенных методов """
|
||||
|
||||
missing_files_count: int = 0
|
||||
""" Счетчик не найденных файлов с тестами """
|
||||
|
||||
missing_classes_count: int = 0
|
||||
""" Счетчик не найденных классов с тестами """
|
||||
|
||||
skipped_packages_count: int = 0
|
||||
""" Счетчик пропущенных пакетов """
|
||||
|
||||
def add_arguments(self, parser):
|
||||
"""
|
||||
Позиционный аргумент: путь к пакету от корня
|
||||
@@ -67,23 +80,19 @@ class Command(BaseCommand):
|
||||
raise CommandError("No package specified for verification.")
|
||||
|
||||
# Метрики и счётчики
|
||||
success_count: int = 0
|
||||
missing_files_count: int = 0
|
||||
missing_classes_count: int = 0
|
||||
skipped_packages_count: int = 0
|
||||
|
||||
for package_name in packages_to_check:
|
||||
package_dir: Path | None = self._find_package_dir(package_name)
|
||||
if not package_dir:
|
||||
self.stdout.write(self.style.WARNING(f"⚠️ Пакет '{package_name}' пропущен: не найдена его директория"))
|
||||
skipped_packages_count += 1
|
||||
self.skipped_packages_count += 1
|
||||
continue
|
||||
|
||||
# Смарт-автообнаружение зеркального пакета тестов вверх по иерархии
|
||||
tests_info: tuple[str, Path] | None = self._autodiscover_tests_package(package_name)
|
||||
if not tests_info:
|
||||
self.stdout.write(self.style.ERROR(f"❌ Не удалось программно найти пакет тестов для: {package_name}"))
|
||||
skipped_packages_count += 1
|
||||
self.skipped_packages_count += 1
|
||||
continue
|
||||
|
||||
tests_root_name, tests_root_dir = tests_info
|
||||
@@ -152,7 +161,7 @@ class Command(BaseCommand):
|
||||
f"❌ Отсутствует файл тестов [{target_file_name}] для метода: {full_path}"
|
||||
)
|
||||
)
|
||||
missing_files_count += 1
|
||||
self.missing_files_count += 1
|
||||
continue
|
||||
|
||||
# 4. СТРОИМ ОЖИДАЕМОЕ ИМЯ КЛАССА ТЕСТОВ
|
||||
@@ -181,26 +190,36 @@ class Command(BaseCommand):
|
||||
f"отсутствует класс [{expected_class_name}] для метода: {full_path}"
|
||||
)
|
||||
)
|
||||
missing_classes_count += 1
|
||||
self.missing_classes_count += 1
|
||||
else:
|
||||
success_count += 1
|
||||
self.success_count += 1
|
||||
|
||||
# Вывод финального промышленного отчёта в терминал
|
||||
total_errors: int = missing_files_count + missing_classes_count
|
||||
self._final_report()
|
||||
|
||||
self.stdout.write("\n" + "=" * 60)
|
||||
self.stdout.write(self.style.SUCCESS(f"📊 ИТОГОВЫЙ ОТЧЁТ ПОКРЫТИЯ МЕТОДОВ:"))
|
||||
self.stdout.write(f" ✅ Успешно проверено и покрыто методов: {success_count}")
|
||||
if skipped_packages_count > 0:
|
||||
self.stdout.write(self.style.WARNING(f" ⚠️ Пропущено / не найдено пакетов: {skipped_packages_count}"))
|
||||
if missing_files_count > 0:
|
||||
self.stdout.write(self.style.ERROR(f" ❌ Отсутствует файлов тестов: {missing_files_count}"))
|
||||
if missing_classes_count > 0:
|
||||
self.stdout.write(self.style.ERROR(f" ❌ Отсутствует классов внутри файлов тестов: {missing_classes_count}"))
|
||||
self.stdout.write("=" * 60 + "\n")
|
||||
def _final_report(self):
|
||||
"""
|
||||
Выводит финальный отчёт в терминал
|
||||
"""
|
||||
|
||||
total_errors: int = self.missing_files_count + self.missing_classes_count
|
||||
|
||||
self._report_separator(first_new_line=True)
|
||||
self.stdout.write(self.style.SUCCESS(f"Test coverage report:"))
|
||||
self._report_separator(double=False)
|
||||
self._report_int_value("Success", self.success_count)
|
||||
if self.skipped_packages_count > 0:
|
||||
self._report_int_value("Skipped packages", self.skipped_packages_count)
|
||||
if self.missing_files_count > 0:
|
||||
self._report_int_value("Missing test files", self.missing_files_count)
|
||||
if self.missing_classes_count > 0:
|
||||
self._report_int_value("Missing test classes", self.missing_classes_count)
|
||||
self._report_separator(double=False, last_new_line=False)
|
||||
|
||||
if total_errors > 0:
|
||||
raise CommandError(f"🛑 Проверка провалена. Суммарно пропущено проверок: {total_errors}")
|
||||
self._report_int_value("Test coverage failed, total number of errors", total_errors)
|
||||
self._report_separator(double=False, last_new_line=False)
|
||||
sys.exit(1)
|
||||
|
||||
@classmethod
|
||||
def _extract_classes_and_methods(cls, file_path: Path, module_dot_path: str) -> list[tuple[str, str | None, str]]:
|
||||
|
||||
Reference in New Issue
Block a user