|
2 | 2 | from __future__ import annotations |
3 | 3 |
|
4 | 4 | import io |
| 5 | +import os |
| 6 | +import sys |
| 7 | +import tempfile |
| 8 | +import unittest |
| 9 | +from contextlib import redirect_stderr, redirect_stdout |
5 | 10 | from pathlib import Path |
6 | | - |
7 | | -import pytest |
| 11 | +from unittest.mock import patch |
8 | 12 |
|
9 | 13 | from evolution_kernel import init_wizard |
10 | 14 | from evolution_kernel.config import load_config |
11 | 15 |
|
12 | 16 |
|
13 | | -@pytest.mark.parametrize("idx,name", list(enumerate(init_wizard.TEMPLATES, start=1))) |
14 | | -def test_each_template_round_trips(tmp_path: Path, monkeypatch, capsys, idx: int, name: str) -> None: |
15 | | - monkeypatch.chdir(tmp_path) |
16 | | - answers = iter([f"unit test mission for {name}", str(idx), "src/, tests/"]) |
17 | | - monkeypatch.setattr("builtins.input", lambda _prompt: next(answers)) |
18 | | - |
19 | | - rc = init_wizard.main([]) |
20 | | - |
21 | | - assert rc == 0, f"init failed for template {name}: {capsys.readouterr().err}" |
22 | | - out = tmp_path / "evolution.yml" |
23 | | - assert out.exists() |
24 | | - cfg = load_config(str(out)) |
25 | | - assert cfg.mission.startswith("unit test mission") |
26 | | - assert cfg.mutation_scope.allowed_paths == ("src/", "tests/") |
27 | | - |
28 | | - |
29 | | -def test_refuses_to_overwrite(tmp_path: Path, monkeypatch, capsys) -> None: |
30 | | - monkeypatch.chdir(tmp_path) |
31 | | - (tmp_path / "evolution.yml").write_text("placeholder\n") |
32 | | - monkeypatch.setattr("builtins.input", lambda _prompt: "x") |
33 | | - assert init_wizard.main([]) == 2 |
34 | | - assert "already exists" in capsys.readouterr().err |
35 | | - |
36 | | - |
37 | | -def test_bad_template_pick(tmp_path: Path, monkeypatch, capsys) -> None: |
38 | | - monkeypatch.chdir(tmp_path) |
39 | | - answers = iter(["mission", "99", "src/"]) |
40 | | - monkeypatch.setattr("builtins.input", lambda _prompt: next(answers)) |
41 | | - assert init_wizard.main([]) == 2 |
| 17 | +class InitWizardTests(unittest.TestCase): |
| 18 | + def setUp(self) -> None: |
| 19 | + self._tmp = tempfile.TemporaryDirectory() |
| 20 | + self.tmp = Path(self._tmp.name) |
| 21 | + self._prev_cwd = os.getcwd() |
| 22 | + os.chdir(self.tmp) |
| 23 | + |
| 24 | + def tearDown(self) -> None: |
| 25 | + os.chdir(self._prev_cwd) |
| 26 | + self._tmp.cleanup() |
| 27 | + |
| 28 | + def _run_with_inputs(self, inputs: list[str]) -> int: |
| 29 | + it = iter(inputs) |
| 30 | + with patch("builtins.input", lambda _prompt: next(it)), redirect_stdout(io.StringIO()), redirect_stderr(io.StringIO()): |
| 31 | + return init_wizard.main([]) |
| 32 | + |
| 33 | + def test_each_template_round_trips(self) -> None: |
| 34 | + for idx, name in enumerate(init_wizard.TEMPLATES, start=1): |
| 35 | + with self.subTest(template=name): |
| 36 | + out_path = self.tmp / "evolution.yml" |
| 37 | + out_path.unlink(missing_ok=True) |
| 38 | + rc = self._run_with_inputs([f"unit test mission for {name}", str(idx), "src/, tests/"]) |
| 39 | + self.assertEqual(rc, 0, f"init failed for {name}") |
| 40 | + self.assertTrue(out_path.exists()) |
| 41 | + cfg = load_config(str(out_path)) |
| 42 | + self.assertTrue(cfg.mission.startswith("unit test mission")) |
| 43 | + self.assertEqual(cfg.mutation_scope.allowed_paths, ("src/", "tests/")) |
| 44 | + |
| 45 | + def test_refuses_to_overwrite(self) -> None: |
| 46 | + (self.tmp / "evolution.yml").write_text("placeholder\n") |
| 47 | + rc = self._run_with_inputs(["x"]) |
| 48 | + self.assertEqual(rc, 2) |
| 49 | + |
| 50 | + def test_bad_template_pick(self) -> None: |
| 51 | + rc = self._run_with_inputs(["mission", "99", "src/"]) |
| 52 | + self.assertEqual(rc, 2) |
| 53 | + |
| 54 | + |
| 55 | +if __name__ == "__main__": # pragma: no cover |
| 56 | + unittest.main() |
0 commit comments