okami.mom/albedo

git clone https://git.nkp.pet/okami.mom/albedo

nekomimi.pettest: run the wall-clock-timed modules first and alone, not beside a hundred others9b3df98

main
6.9 KiB174 linesraw
1"""Empty test selections must fail before the gate can report success.
2
3Application E2E cannot detect deleted test methods or runner discovery errors.
4Use temporary suites and the real runner processes, without starting a daemon.
5"""
6
7import os
8from pathlib import Path
9import re
10import subprocess
11import sys
12import tempfile
13import unittest
14
15ROOT = Path(__file__).resolve().parents[2]
16
17
18class TestRunnerTests(unittest.TestCase):
19    def test_the_timed_modules_the_gleam_runner_runs_alone_still_exist(self):
20        # The runner skips a name it does not find, so a renamed module would
21        # quietly rejoin the parallel burst whose load its windows cannot take.
22        source = (ROOT / "test/albedo_test_runner.erl").read_text()
23        match = re.search(r"-define\(TIMED, \[(.*?)\]\)", source, re.S)
24        assert match, "the runner no longer names its timed modules"
25        names = re.findall(r"'([^']+)'", match.group(1))
26        self.assertTrue(names)
27        for name in names:
28            with self.subTest(name):
29                path = ROOT / "test" / (name.replace("@", "/") + ".gleam")
30                self.assertTrue(path.is_file(), f"{path} no longer exists")
31
32    def test_python_runner_rejects_empty_files_and_preserves_failure_exit(self):
33        with tempfile.TemporaryDirectory() as directory:
34            path = Path(directory) / "example_test.py"
35            for source, successful, message in [
36                ("import unittest\n", False, "no tests collected"),
37                (
38                    "import unittest\nclass Example(unittest.TestCase):\n"
39                    "    def test_works(self): self.assertTrue(True)\n",
40                    True,
41                    "Ran 1 test",
42                ),
43                (
44                    "import unittest\nclass Example(unittest.TestCase):\n"
45                    "    def test_fails(self): self.fail('fixture failure')\n",
46                    False,
47                    "fixture failure",
48                ),
49            ]:
50                with self.subTest(source=source):
51                    path.write_text(source)
52                    result = subprocess.run(
53                        [
54                            sys.executable,
55                            str(ROOT / "test/python_test_runner.py"),
56                            str(path),
57                        ],
58                        capture_output=True,
59                        text=True,
60                        timeout=15,
61                    )
62                    self.assertEqual(result.returncode == 0, successful, result.stderr)
63                    self.assertIn(message, result.stderr)
64
65    def test_e2e_rejects_empty_file_among_valid_files_and_empty_aggregate(self):
66        script = """
67import sys, unittest
68from pathlib import Path
69sys.path.insert(0, str(Path('test/e2e').resolve()))
70import run
71root = Path(sys.argv[1])
72valid = root / 'valid_test.py'
73suite = run.suite_for(valid, 'Example.test_works')
74assert suite.countTestCases() == 1
75assert unittest.TextTestRunner().run(suite).wasSuccessful()
76for collect in [
77    lambda: unittest.TestSuite(run.suite_for(p) for p in sorted(root.glob('*_test.py'))),
78    lambda: run.run_suite(unittest.TestSuite(), 1, 1),
79]:
80    try:
81        collect()
82    except ValueError as error:
83        assert 'no ' in str(error) and 'tests collected' in str(error), str(error)
84    else:
85        raise AssertionError('empty selection passed')
86"""
87        with tempfile.TemporaryDirectory() as directory:
88            root = Path(directory)
89            (root / "empty_test.py").write_text("import unittest\n")
90            (root / "valid_test.py").write_text(
91                "import unittest\nclass Example(unittest.TestCase):\n"
92                "    def test_works(self): pass\n"
93            )
94            result = subprocess.run(
95                [sys.executable, "-c", script, directory],
96                cwd=ROOT,
97                capture_output=True,
98                text=True,
99                timeout=15,
100            )
101            self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
102
103    def test_erlang_runner_requires_test_exports_but_ignores_support(self):
104        with tempfile.TemporaryDirectory() as directory:
105            root = Path(directory)
106            tests = root / "test"
107            tests.mkdir()
108            sources = [
109                ROOT / "test/albedo_test_runner.erl",
110                ROOT / "test/albedo_test_home.erl",
111            ]
112            subprocess.run(
113                ["erlc", "-Werror", "-o", directory, *map(str, sources)],
114                check=True,
115                timeout=30,
116            )
117            for source, successful, message in [
118                (None, False, "no_test_modules"),
119                (
120                    "-module(example_test).\n-export([helper/0]).\nhelper() -> ok.\n",
121                    False,
122                    "no_tests_in_module",
123                ),
124                (
125                    '-module(example_test).\n-include_lib("eunit/include/eunit.hrl").\n'
126                    "ordinary_test() -> ?assert(true).\n"
127                    "generated_test_() -> [?_assert(true)].\n",
128                    True,
129                    "",
130                ),
131            ]:
132                with self.subTest(source=source):
133                    if source is not None:
134                        path = tests / "example_test.erl"
135                        path.write_text(source)
136                        subprocess.run(
137                            ["erlc", "-Werror", "-o", directory, str(path)],
138                            check=True,
139                            timeout=30,
140                        )
141                    (tests / "fixture.erl").write_text(
142                        "intentionally not a compiled test module\n"
143                    )
144                    # The actual Gleam entrypoint and fixtures must be excluded.
145                    (tests / "albedo_test.gleam").write_text("pub fn main() { Nil }\n")
146                    paths = [directory, str(ROOT / "build/dev/erlang/gleeunit/ebin")]
147                    result = subprocess.run(
148                        [
149                            "erl",
150                            "+S",
151                            "2:2",
152                            "-pa",
153                            *paths,
154                            "-noshell",
155                            "-eval",
156                            "albedo_test_home:isolate(), albedo_test_runner:main().",
157                        ],
158                        cwd=root,
159                        env={**os.environ, "ALBEDO_TEST_TMP": str(root / "scratch")},
160                        capture_output=True,
161                        text=True,
162                        timeout=30,
163                    )
164                    self.assertEqual(
165                        result.returncode == 0,
166                        successful,
167                        result.stdout + result.stderr,
168                    )
169                    if message:
170                        self.assertIn(message, result.stdout + result.stderr)
171
172
173if __name__ == "__main__":
174    unittest.main()