# -*- coding: utf-8 -*- """Общие утилиты исполняемой самопроверки (используют verify.py и webui.py).""" import os import subprocess import sys TEST_SYSTEM = ("Ты — инженер по тестированию. Пиши исчерпывающие юнит-тесты на стандартной " "библиотеке unittest. Тесты должны реально проверять корректность решения, " "включая крайние случаи. Не пиши реализацию — только тесты.") VERIFY_ATTEMPTS = 5 VERIFY_TIMEOUT = 30 def run_tests(code, tests, workdir, timeout=VERIFY_TIMEOUT): """Пишет код и тесты в песочницу и гоняет unittest. Возвращает (ok, вывод).""" with open(os.path.join(workdir, "solution.py"), "w", encoding="utf-8") as f: f.write(code) with open(os.path.join(workdir, "test_solution.py"), "w", encoding="utf-8") as f: f.write(tests) try: r = subprocess.run( [sys.executable, "-m", "unittest", "test_solution", "-v"], cwd=workdir, capture_output=True, text=True, timeout=timeout, ) out = (r.stdout or "") + "\n" + (r.stderr or "") return r.returncode == 0, out.strip() except subprocess.TimeoutExpired: return False, f"ТЕСТЫ ЗАВИСЛИ (таймаут {timeout}с)" def looks_like_tests(text): """Эвристика: ответ модели — это тесты или код?""" return ("import unittest" in text or "unittest" in text or "class Test" in text or "def test_" in text or ("assert" in text and "def " not in text)) def tail(s, n=900): """Хвост вывода — самое важное (финальный трейсбек).""" s = s.strip() return s if len(s) <= n else "…\n" + s[-n:] def ensure_unittest_header(tests): """Если модель забыла импорт unittest — добавляем заглушку-заголовок.""" if "import unittest" not in tests and "unittest" not in tests: return "import unittest\nfrom solution import *\n\n" + tests return tests