Coverage for tests / cli / supervisors / test_watchfiles.py: 90%
30 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-05-08 01:48 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-05-08 01:48 +0000
1import os
2import signal
3import time
4from multiprocessing.context import SpawnProcess
5from pathlib import Path
6from unittest.mock import MagicMock, patch
8import pytest
10from faststream._internal.cli.dto import RunArgs
11from faststream._internal.cli.supervisors.utils import get_subprocess
12from faststream._internal.cli.supervisors.watchfiles import WatchReloader
13from tests.cli import interfaces
14from tests.marks import skip_windows
16DIR = Path(__file__).resolve().parent
19class PatchedWatchReloader(WatchReloader):
20 def start_process(self, worker_id: int | None = None) -> SpawnProcess:
21 process = get_subprocess(target=self._target, args=(self._args,))
22 process.start()
23 return process
26@pytest.mark.slow()
27@skip_windows
28def test_base(generate_template: interfaces.GenerateTemplateFactory) -> None:
29 with generate_template("") as file_path:
30 processor = PatchedWatchReloader(
31 target=exit,
32 args=RunArgs(app=""),
33 reload_dirs=[str(file_path.parent)],
34 )
36 processor._args.extra_options = {"parent_id": processor.pid}
37 processor.run()
39 code = abs(processor._process.exitcode or 0)
41 assert code in {signal.SIGTERM.value, 0}, code
44@pytest.mark.slow()
45@skip_windows
46def test_restart(
47 mock: MagicMock, generate_template: interfaces.GenerateTemplateFactory
48) -> None:
49 with generate_template("") as file_path:
50 processor = PatchedWatchReloader(
51 target=touch_file,
52 args=RunArgs(app=str(file_path)),
53 reload_dirs=[file_path.parent],
54 )
56 mock.side_effect = lambda: exit(
57 RunArgs(app="", extra_options={"parent_id": processor.pid})
58 )
60 with patch.object(processor, "restart", mock):
61 processor.run()
63 mock.assert_called_once()
66def touch_file(args: RunArgs) -> None:
67 while True:
68 time.sleep(0.1)
69 Path(args.app).write_text("hello", encoding="utf-8")
72def exit(args: RunArgs) -> None:
73 os.kill(int(args.extra_options["parent_id"]), signal.SIGINT)