zapretgui/tests/test_process_start_time.py
loop-uh dea5b115cf Speed up startup: ExeToPython metric, lazy imports, qtawesome warmup
Метрика и инструментация:
- StartupExeToPython: разрыв от создания процесса (GetProcessTimes) до
  входа в Python — раньше bootloader/DLL/антивирус были невидимы
- Пофасадные метрики StartupFeatureFacadeImport.*, разбивка attach-цепочки
  и _build_ui первой страницы

Ленивые импорты (тёплый Interactive 1.85s -> ~1.0s, окно 1.5s -> ~0.7s):
- orchestra/ignored_targets: telegram_proxy больше не тянется на старте
  (весь пакет с asyncio/mtproxy стоил 240ms тёплым, 555ms холодным)
- ui/page_deps/presets: preset_subpage_base/qtawesome не импортируются
  до первого показа окна (~200ms)
- qtawesome греется в фоне после application_bootstrap (не в prelaunch —
  там он отбирает GIL у импортов главного потока); мёртвый jinja2 убран

Контракт: отложенная сборка settings-секций снова пробовалась и снова
откачена (таймеры + интерфейс появлялся дольше) — запрет зафиксирован
в тесте с объяснением.
2026-07-06 12:32:29 +03:00

76 lines
2.7 KiB
Python

from __future__ import annotations
import sys
import time
import unittest
from pathlib import Path
PROJECT_SRC = Path(__file__).resolve().parents[1] / "src"
if str(PROJECT_SRC) not in sys.path:
sys.path.insert(0, str(PROJECT_SRC))
class FiletimeConversionTests(unittest.TestCase):
def test_unix_epoch_converts_to_zero(self) -> None:
from main.process_start_time import filetime_to_unix_seconds
unix_epoch_ticks = 11_644_473_600 * 10_000_000
self.assertEqual(filetime_to_unix_seconds(unix_epoch_ticks), 0.0)
def test_one_second_after_unix_epoch(self) -> None:
from main.process_start_time import filetime_to_unix_seconds
ticks = (11_644_473_600 + 1) * 10_000_000
self.assertEqual(filetime_to_unix_seconds(ticks), 1.0)
@unittest.skipUnless(sys.platform == "win32", "GetProcessTimes есть только на Windows")
class ProcessCreationTimeTests(unittest.TestCase):
def test_creation_time_matches_psutil(self) -> None:
import psutil
from main.process_start_time import process_creation_unix_seconds
created = process_creation_unix_seconds()
self.assertIsNotNone(created)
self.assertAlmostEqual(created, psutil.Process().create_time(), delta=2.0)
def test_creation_time_is_in_the_past(self) -> None:
from main.process_start_time import process_creation_unix_seconds
created = process_creation_unix_seconds()
self.assertIsNotNone(created)
self.assertLessEqual(created, time.time())
@unittest.skipUnless(sys.platform == "win32", "GetProcessTimes есть только на Windows")
class ExeToPythonGapTests(unittest.TestCase):
def test_gap_is_non_negative_and_plausible(self) -> None:
from main.process_start_time import exe_to_python_ms
gap_ms = exe_to_python_ms()
self.assertIsNotNone(gap_ms)
self.assertGreaterEqual(gap_ms, 0)
# Импорт модуля в тестах происходит позже, чем в бою, но всё равно
# в пределах жизни текущего процесса.
one_hour_ms = 60 * 60 * 1000
self.assertLess(gap_ms, one_hour_ms)
def test_gap_consistent_with_entered_wall(self) -> None:
from main.process_start_time import (
exe_to_python_ms,
process_creation_unix_seconds,
python_entered_wall,
)
created = process_creation_unix_seconds()
gap_ms = exe_to_python_ms()
self.assertIsNotNone(created)
self.assertIsNotNone(gap_ms)
expected_ms = (python_entered_wall() - created) * 1000.0
self.assertAlmostEqual(gap_ms, expected_ms, delta=1.0)
if __name__ == "__main__":
unittest.main()