Skip to content

Commit 56080ad

Browse files
committed
test: Stop importing fixer as a module
The dependabot-grpc-fixer is meant to be exercised as a script, not through a dynamically imported module. Run the remaining tests via runpy so they cover the supported entrypoint instead of the script internals. Drop the replace_range() unit test and the shared module loader to reduce coupling to implementation details while keeping the existing script-level coverage. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
1 parent dc9585c commit 56080ad

1 file changed

Lines changed: 7 additions & 67 deletions

File tree

tests/cookiecutter/scripts/test_dependabot-grpc-fixer.py

Lines changed: 7 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,20 @@
11
"""Tests for the dependabot_gprc_fixer package."""
22

3-
import importlib.util
43
import json
54
import re
65
import runpy
76
import shutil
87
import sys
98
from dataclasses import dataclass
109
from pathlib import Path
11-
from typing import Protocol, cast
1210

1311
import pytest
1412

15-
# The script is not intended to be imported as a module, so we load it "dynamically"
16-
# here to test do some unit testing of its internal functions.
1713
FIXER_PATH = (
1814
Path(__file__).resolve().parents[3]
1915
/ "cookiecutter/scripts/dependabot-grpc-fixer.py"
2016
)
21-
22-
23-
class FixerModule(Protocol):
24-
"""Typing contract for the loaded fixer script."""
25-
26-
PYPROJECT: Path
27-
28-
def main(self) -> None:
29-
"""Run the fixer script."""
30-
31-
def replace_range(self, text: str, name: str, version: str) -> tuple[str, int]:
32-
"""Update a dependency range."""
33-
34-
35-
def _load_fixer() -> FixerModule:
36-
"""Load the fixer script as a module for direct testing."""
37-
spec = importlib.util.spec_from_file_location("fixer", FIXER_PATH)
38-
if spec is None or spec.loader is None:
39-
raise AssertionError(f"could not load {FIXER_PATH}")
40-
41-
module = importlib.util.module_from_spec(spec)
42-
spec.loader.exec_module(module)
43-
return cast(FixerModule, module)
44-
45-
46-
fixer = _load_fixer()
17+
PYPROJECT = Path("pyproject.toml")
4718

4819
CASE_ROOT = Path(__file__).with_name("fixtures") / "dependabot-grpc-fixer"
4920

@@ -107,15 +78,15 @@ def _prepare_workspace(
10778
input_dir = case.path / "input"
10879
input_pyproject = input_dir / "pyproject.toml"
10980
if input_pyproject.exists():
110-
shutil.copyfile(input_pyproject, tmp_path / fixer.PYPROJECT.name)
81+
shutil.copyfile(input_pyproject, tmp_path / PYPROJECT.name)
11182
monkeypatch.chdir(tmp_path)
11283
monkeypatch.setattr(sys, "argv", [str(FIXER_PATH)])
11384
input_metadata = input_dir / "dependabot-metadata.json"
11485
monkeypatch.setenv(
11586
"UPDATED_DEPENDENCIES_JSON",
11687
input_metadata.read_text(encoding="utf-8") if input_metadata.exists() else "",
11788
)
118-
return tmp_path / fixer.PYPROJECT.name
89+
return tmp_path / PYPROJECT.name
11990

12091

12192
@pytest.mark.parametrize(
@@ -131,10 +102,10 @@ def test_fixer_cases(
131102
workspace = _prepare_workspace(case, tmp_path, monkeypatch)
132103
if case.stderr_exact is not None or case.stderr_contains is not None:
133104
with pytest.raises(SystemExit) as excinfo:
134-
fixer.main()
105+
runpy.run_path(str(FIXER_PATH), run_name="__main__")
135106
assert excinfo.value.code == 1
136107
else:
137-
fixer.main()
108+
runpy.run_path(str(FIXER_PATH), run_name="__main__")
138109

139110
captured = capsys.readouterr()
140111

@@ -217,37 +188,6 @@ def test_fixer_runs_as_script_with_custom_pyproject_path(
217188
) == case.expected_pyproject.read_text(encoding="utf-8")
218189

219190

220-
@pytest.mark.parametrize(
221-
("dependency", "version", "original", "expected"),
222-
[
223-
(
224-
"grpcio",
225-
"2.0.0",
226-
'"grpcio >= 1.72.1, < 2", # Do not widen beyond 2!',
227-
'"grpcio >= 2.0.0, < 3", # Do not widen beyond 3!',
228-
),
229-
(
230-
"protobuf",
231-
"7.34.1",
232-
'"protobuf >= 6.32.1, < 7", # Do not widen beyond 7!',
233-
'"protobuf >= 7.34.1, < 9", # Do not widen beyond 9!',
234-
),
235-
],
236-
ids=lambda case: case[0],
237-
)
238-
def test_replace_range_uses_dependency_specific_upper_bounds(
239-
dependency: str,
240-
version: str,
241-
original: str,
242-
expected: str,
243-
) -> None:
244-
"""Use the configured compatibility window for each runtime dependency."""
245-
updated, count = fixer.replace_range(original, dependency, version)
246-
247-
assert count == 1
248-
assert updated == expected
249-
250-
251191
# Integration: run the fixer against pyproject.toml files generated by the
252192
# cookiecutter template (as captured in tests_golden/). The fixer only applies
253193
# to API repositories, so we discover every `api*` golden case automatically.
@@ -384,7 +324,7 @@ def test_fixer_against_generated_api_pyproject(
384324
assert expected_protobuf_upper != protobuf_upper
385325
assert expected_grpcio_upper != grpcio_upper
386326

387-
workspace = tmp_path / fixer.PYPROJECT.name
327+
workspace = tmp_path / PYPROJECT.name
388328
shutil.copyfile(golden_pyproject, workspace)
389329
monkeypatch.chdir(tmp_path)
390330
monkeypatch.setattr(sys, "argv", [str(FIXER_PATH)])
@@ -395,7 +335,7 @@ def test_fixer_against_generated_api_pyproject(
395335
),
396336
)
397337

398-
fixer.main()
338+
runpy.run_path(str(FIXER_PATH), run_name="__main__")
399339

400340
captured = capsys.readouterr()
401341
assert (

0 commit comments

Comments
 (0)