Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
288ff3b
Add tests
Kilka0s0Tomatami Mar 25, 2026
f49be42
Add files via upload
Kilka0s0Tomatami May 5, 2026
2b7d3d8
Add files via upload
Kilka0s0Tomatami May 25, 2026
ef7f386
Add files via upload
Kilka0s0Tomatami May 25, 2026
6212345
Update test_empty_slide_check.py
Kilka0s0Tomatami May 25, 2026
587989b
Add files via upload
Kilka0s0Tomatami May 25, 2026
008402a
Delete tests/presentations/banned_words.py
Kilka0s0Tomatami May 25, 2026
cbe63f8
Delete tests/presentations/decimal_places.py
Kilka0s0Tomatami May 25, 2026
17597a1
Delete tests/presentations/template_name.py
Kilka0s0Tomatami May 25, 2026
2f76741
Delete tests/presentations/further_dev.py
Kilka0s0Tomatami May 25, 2026
54a25c6
Delete tests/presentations/find_def_sld.py
Kilka0s0Tomatami May 25, 2026
22cb515
Delete tests/presentations/empty_slide_check.py
Kilka0s0Tomatami May 25, 2026
98f0915
Delete tests/presentations/image_share.py
Kilka0s0Tomatami May 25, 2026
1a04c09
Delete tests/presentations/name_of_image_check.py
Kilka0s0Tomatami May 25, 2026
73b8f60
Delete tests/presentations/find_tasks.py
Kilka0s0Tomatami May 25, 2026
9e840d1
Delete tests/presentations/task_tracker.py
Kilka0s0Tomatami May 25, 2026
2aef6de
Delete tests/presentations/find_theme_in_pres.py
Kilka0s0Tomatami May 25, 2026
04c531e
Delete tests/presentations/sld_enum.py
Kilka0s0Tomatami May 25, 2026
3c99f9a
Delete tests/presentations/slide_headers_duplication_check.py
Kilka0s0Tomatami May 25, 2026
70abd98
Delete tests/presentations/search_keyword.py
Kilka0s0Tomatami May 25, 2026
8b3151b
Delete tests/presentations/pres_right_words.py
Kilka0s0Tomatami May 25, 2026
e4b2b20
Delete tests/presentations/sld_num.py
Kilka0s0Tomatami May 25, 2026
628bdb5
Delete tests/presentations/overview_in_tasks.py
Kilka0s0Tomatami May 25, 2026
b25e011
Delete tests/presentations/sld_similarity.py
Kilka0s0Tomatami May 25, 2026
39fe49e
Delete tests/presentations/title_format.py
Kilka0s0Tomatami May 25, 2026
bdef3bc
Delete tests/presentations/verify_git_link.py
Kilka0s0Tomatami May 25, 2026
d89fb7d
Add files via upload
Kilka0s0Tomatami May 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 90 additions & 67 deletions app/main/checks/presentation_checks/empty_slide_check.py
Original file line number Diff line number Diff line change
@@ -1,67 +1,90 @@
import re

from app.utils.parse_for_html import format_header
from ..base_check import BasePresCriterion, answer


class PresEmptySlideCheck(BasePresCriterion):
label = "Проверка наличия пустых слайдов в презентации"
_description = ""
id = 'pres_empty_slide'

def __init__(self, file_info, status=False):
super().__init__(file_info)
self.status = status

def check(self):
result_str = ''
page_titles = {}
full_pages = {}
empty_pages = []
pages_with_title = []

pages_with_images = [page for page, slide in enumerate(self.file.slides, 1)
if slide.get_images() or slide.get_table()]

for page, slide in enumerate(self.file.get_text_from_slides(), 1):
slide_string = ''.join(slide.replace("\n", " "))
slide_without_page = re.sub(r'\d+(?=\s*$)', '', slide_string)
full_pages[str(page)] = ''.join(char for char in slide_without_page.strip() if char.isprintable())
if not full_pages[str(page)]:
empty_pages.append(page)

for page, slide in enumerate(self.file.get_titles(), 1):
page_titles[str(page)] = slide
if slide != "Запасные слайды":
if slide == full_pages[str(page)] and page not in pages_with_images and page not in empty_pages:
pages_with_title.append(page)

if self.file.presentation_name.endswith('.ppt') or self.file.presentation_name.endswith('.pptx'):

if empty_pages and not pages_with_title:
result_str += format_header(
'Не пройдена! Обнаружены пустые слайды: {}'.format(
', '.join(self.format_page_link(empty_pages)))
)
if pages_with_title and not empty_pages:
result_str += format_header(
'Не пройдена! Обнаружены слайды, в которых присутствует только заголовок: {}'.format(
', '.join(self.format_page_link(pages_with_title)))
)
if empty_pages and pages_with_title:
result_str += format_header(
'Не пройдена! Обнаружены пустые слайды: {}, также обнаружены слайды, в которых присутствует только заголовок: {}'.format(
', '.join(self.format_page_link(empty_pages)), ', '.join(self.format_page_link(pages_with_title)))
)
elif self.file.presentation_name.lower().endswith('.odp'):
if empty_pages:
result_str += format_header(
'Не пройдена! Обнаружены пустые слайды или слайды, в которых присутствует только заголовок: {}'.format(
', '.join(self.format_page_link(empty_pages)))
)

if not result_str:
self.status = True
result_str = 'Пройдена!'

return answer(self.status, result_str)
import re

from app.utils.parse_for_html import format_header
from ..base_check import BasePresCriterion, answer
from app.main.presentations.presentation_basic import PresentationBasic


class CheckResult:
def __init__(self, status, result_str):
self.status = status
self.result_str = result_str


class PresEmptySlideCheck(BasePresCriterion):
label = "Проверка наличия пустых слайдов в презентации"
_description = ""
id = 'pres_empty_slide'

def __init__(self, file_info, status=False):
if isinstance(file_info, str):
# Прямой путь к файлу — используется в тестах
self.filename = file_info
self.pdf_id = None
self.file_type = None
self.status = status
if file_info.endswith('.pptx') or file_info.endswith('.ppt'):
from app.main.presentations.pptx.presentation_pptx import PresentationPPTX
self.file = PresentationPPTX(file_info)
elif file_info.lower().endswith('.odp'):
from app.main.presentations.odp.presentation_odp import PresentationODP
self.file = PresentationODP(file_info)
else:
# Неподдерживаемый формат — пустая заглушка
self.file = PresentationBasic(file_info)
else:
# Стандартный путь через проект — словарь file_info
super().__init__(file_info)
self.status = status

def check(self):
result_str = ''
page_titles = {}
full_pages = {}
empty_pages = []
pages_with_title = []

pages_with_images = [page for page, slide in enumerate(self.file.slides, 1)
if slide.get_images() or slide.get_table()]

for page, slide in enumerate(self.file.get_text_from_slides(), 1):
slide_string = ''.join(slide.replace("\n", " "))
slide_without_page = re.sub(r'\d+(?=\s*$)', '', slide_string)
full_pages[str(page)] = ''.join(char for char in slide_without_page.strip() if char.isprintable())
if not full_pages[str(page)] and page not in pages_with_images:
empty_pages.append(page)

for page, slide in enumerate(self.file.get_titles(), 1):
page_titles[str(page)] = slide
if slide != "Запасные слайды":
if slide == full_pages[str(page)] and page not in pages_with_images and page not in empty_pages:
pages_with_title.append(page)

if self.file.presentation_name.endswith('.ppt') or self.file.presentation_name.endswith('.pptx'):
if empty_pages and not pages_with_title:
result_str += format_header(
'Не пройдена! Обнаружены пустые слайды: {}'.format(
', '.join(self.format_page_link(empty_pages)))
)
if pages_with_title and not empty_pages:
result_str += format_header(
'Не пройдена! Обнаружены слайды, в которых присутствует только заголовок: {}'.format(
', '.join(self.format_page_link(pages_with_title)))
)
if empty_pages and pages_with_title:
result_str += format_header(
'Не пройдена! Обнаружены пустые слайды: {}, также обнаружены слайды, в которых присутствует только заголовок: {}'.format(
', '.join(self.format_page_link(empty_pages)), ', '.join(self.format_page_link(pages_with_title)))
)
elif self.file.presentation_name.lower().endswith('.odp'):
if empty_pages:
result_str += format_header(
'Не пройдена! Обнаружены пустые слайды или слайды, в которых присутствует только заголовок: {}'.format(
', '.join(self.format_page_link(empty_pages)))
)

if not result_str:
self.status = True
result_str = 'Пройдена!'

return CheckResult(self.status, result_str)
Empty file added tests/__init__.py
Empty file.
42 changes: 42 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import pytest
import sys
from pathlib import Path

project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))

@pytest.fixture
def presentations_fixtures_dir():
return Path(__file__).parent / "fixtures" / "presentations"

@pytest.fixture
def find_tasks_fixtures_dir(presentations_fixtures_dir):
return presentations_fixtures_dir / "find_tasks"

@pytest.fixture
def further_dev_fixtures_dir(presentations_fixtures_dir):
return presentations_fixtures_dir / "further_dev"

@pytest.fixture
def image_capture_fixtures_dir(presentations_fixtures_dir):
return presentations_fixtures_dir / "image_capture"

@pytest.fixture
def right_words_fixtures_dir(presentations_fixtures_dir):
return presentations_fixtures_dir / "right_words"

@pytest.fixture
def sld_enum_fixtures_dir(presentations_fixtures_dir):
return presentations_fixtures_dir / "sld_enum"

@pytest.fixture
def sld_similarity_fixtures_dir(presentations_fixtures_dir):
return presentations_fixtures_dir / "sld_similarity"

@pytest.fixture
def task_tracker_fixtures_dir(presentations_fixtures_dir):
return presentations_fixtures_dir / "task_tracker"

@pytest.fixture
def title_format_fixtures_dir(presentations_fixtures_dir):
return presentations_fixtures_dir / "title_format"
Empty file added tests/fixtures/__init__.py
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
15 changes: 15 additions & 0 deletions tests/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
def make_file_info(path_str):
if path_str.endswith(('.pptx', '.ppt')):
from app.main.presentations.pptx.presentation_pptx import PresentationPPTX
file_obj = PresentationPPTX(path_str)
elif path_str.lower().endswith('.odp'):
from app.main.presentations.odp.presentation_odp import PresentationODP
file_obj = PresentationODP(path_str)
else:
from app.main.presentations.presentation_basic import PresentationBasic
file_obj = PresentationBasic(path_str)
return {'file': file_obj, 'filename': path_str, 'pdf_id': None, 'file_type': None}


def verdict_str(result):
return ' '.join(str(v) for v in result['verdict'])
Empty file added tests/presentations/__init__.py
Empty file.
15 changes: 15 additions & 0 deletions tests/presentations/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
def make_file_info(path_str):
if path_str.endswith(('.pptx', '.ppt')):
from app.main.presentations.pptx.presentation_pptx import PresentationPPTX
file_obj = PresentationPPTX(path_str)
elif path_str.lower().endswith('.odp'):
from app.main.presentations.odp.presentation_odp import PresentationODP
file_obj = PresentationODP(path_str)
else:
from app.main.presentations.presentation_basic import PresentationBasic
file_obj = PresentationBasic(path_str)
return {'file': file_obj, 'filename': path_str, 'pdf_id': None, 'file_type': None}


def verdict_str(result):
return ' '.join(str(v) for v in result['verdict'])
51 changes: 51 additions & 0 deletions tests/presentations/test_empty_slide_check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import pytest
from app.main.checks.presentation_checks.empty_slide_check import PresEmptySlideCheck
from helpers import make_file_info, verdict_str


class TestPresEmptySlideCheck:

def _make_checker(self, path, **kwargs):
return PresEmptySlideCheck(make_file_info(str(path)), **kwargs)

def test_01_valid_presentation(self, presentations_fixtures_dir):
checker = self._make_checker(presentations_fixtures_dir / "empty_slide_check" / "valid.pptx")
result = checker.check()
assert result['score'] == 1.0
assert verdict_str(result) == "Пройдена!"

def test_02_detect_empty_slides(self, presentations_fixtures_dir):
checker = self._make_checker(presentations_fixtures_dir / "empty_slide_check" / "with_empty_slides.pptx")
result = checker.check()
assert result['score'] == 0.0
assert "Не пройдена" in verdict_str(result)
assert "пустые слайды" in verdict_str(result)
assert "2" in verdict_str(result)
assert "4" in verdict_str(result)

def test_03_detect_title_only_slides(self, presentations_fixtures_dir):
checker = self._make_checker(presentations_fixtures_dir / "empty_slide_check" / "with_title_only.pptx")
result = checker.check()
assert result['score'] == 0.0
assert "Не пройдена" in verdict_str(result)
assert "только заголовок" in verdict_str(result)
assert "1" in verdict_str(result)
assert "3" in verdict_str(result)

def test_04_images_and_tables_as_content(self, presentations_fixtures_dir):
checker = self._make_checker(presentations_fixtures_dir / "empty_slide_check" / "with_images_tables.pptx")
result = checker.check()
assert result['score'] == 1.0
assert verdict_str(result) == "Пройдена!"

def test_05_backup_slide_ignored(self, presentations_fixtures_dir):
checker = self._make_checker(presentations_fixtures_dir / "empty_slide_check" / "with_backup_slide.pptx")
result = checker.check()
assert result['score'] == 1.0
assert verdict_str(result) == "Пройдена!"

def test_06_unsupported_format(self, presentations_fixtures_dir):
checker = self._make_checker(presentations_fixtures_dir / "empty_slide_check" / "empty.pdf")
result = checker.check()
assert result['score'] == 1.0
assert verdict_str(result) == "Пройдена!"
45 changes: 45 additions & 0 deletions tests/presentations/test_find_tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import pytest
from app.main.checks.presentation_checks.find_tasks import FindTasks
from helpers import make_file_info, verdict_str


class TestFindTasks:

def _make_checker(self, path, **kwargs):
return FindTasks(make_file_info(str(path)), **kwargs)

def test_01_all_tasks_found(self, find_tasks_fixtures_dir):
checker = self._make_checker(find_tasks_fixtures_dir / "all_tasks_found.pptx")
result = checker.check()
assert result['score'] == 1.0
assert verdict_str(result) == "Все задачи найдены на слайдах"

def test_02_goal_slide_not_found(self, find_tasks_fixtures_dir):
checker = self._make_checker(find_tasks_fixtures_dir / "no_goal_slide.pptx")
result = checker.check()
assert result['score'] == 0.0
assert verdict_str(result) == 'Слайд "Задачи" не найден'

def test_03_below_threshold(self, find_tasks_fixtures_dir):
checker = self._make_checker(find_tasks_fixtures_dir / "below_threshold.pptx")
result = checker.check()
assert result['score'] == pytest.approx(0.4)
assert "не найдены" in verdict_str(result) or "Не найдены" in verdict_str(result)

def test_04_above_threshold(self, find_tasks_fixtures_dir):
checker = self._make_checker(find_tasks_fixtures_dir / "above_threshold.pptx")
result = checker.check()
assert result['score'] == 1.0
assert verdict_str(result) == "Все задачи найдены на слайдах"

def test_05_boundary_value(self, find_tasks_fixtures_dir):
checker = self._make_checker(find_tasks_fixtures_dir / "boundary_value.pptx")
result = checker.check()
assert result['score'] == pytest.approx(0.5)
assert "не найдены" in verdict_str(result) or "Не найдены" in verdict_str(result)

def test_06_custom_threshold(self, find_tasks_fixtures_dir):
checker = self._make_checker(find_tasks_fixtures_dir / "custom_threshold.pptx", min_percent=70)
result = checker.check()
assert result['score'] == pytest.approx(0.8)
assert "найдены" in verdict_str(result) or "Найдены" in verdict_str(result)
51 changes: 51 additions & 0 deletions tests/presentations/test_further_dev.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import pytest
from app.main.checks.presentation_checks.further_dev import FurtherDev
from helpers import make_file_info, verdict_str


class TestFurtherDev:

def _make_checker(self, path, **kwargs):
return FurtherDev(make_file_info(str(path)), **kwargs)

def test_01_further_dev_found(self, further_dev_fixtures_dir):
checker = self._make_checker(further_dev_fixtures_dir / "further_dev_found.pptx")
result = checker.check()
assert result['score'] == 1.0
assert verdict_str(result) == "Направления развития найдены"

def test_02_conclusion_not_exists(self, further_dev_fixtures_dir):
checker = self._make_checker(further_dev_fixtures_dir / "no_conclusion.pptx")
result = checker.check()
assert result['score'] == 0.0
assert verdict_str(result) == "Заключения не существует"

def test_03_no_further_dev_in_conclusion(self, further_dev_fixtures_dir):
checker = self._make_checker(further_dev_fixtures_dir / "no_further_dev.pptx")
result = checker.check()
assert result['score'] == 0.0
assert "Направления развития не найдены" in verdict_str(result)

def test_04_custom_conclusion_title(self, further_dev_fixtures_dir):
checker = self._make_checker(further_dev_fixtures_dir / "custom_conclusion.pptx", conclusion="Выводы и перспективы")
result = checker.check()
assert result['score'] == 1.0
assert verdict_str(result) == "Направления развития найдены"

def test_05_indirect_indicators(self, further_dev_fixtures_dir):
checker = self._make_checker(further_dev_fixtures_dir / "indirect_indicators.pptx")
result = checker.check()
assert result['score'] == 1.0
assert verdict_str(result) == "Направления развития найдены"

def test_06_different_formats(self, further_dev_fixtures_dir):
# ⚠️ .ppt (старый бинарный формат) не поддерживается python-pptx — тест упадёт с ошибкой открытия файла
checker_ppt = self._make_checker(further_dev_fixtures_dir / "further_dev_found.ppt")
result_ppt = checker_ppt.check()
assert result_ppt['score'] == 1.0
assert verdict_str(result_ppt) == "Направления развития найдены"

checker_odp = self._make_checker(further_dev_fixtures_dir / "further_dev_found.odp")
result_odp = checker_odp.check()
assert result_odp['score'] == 1.0
assert verdict_str(result_odp) == "Направления развития найдены"
Loading
Loading