Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,13 @@ repos:
always_run: true
pass_filenames: false
priority: 0
- repo: local
hooks:
- id: check-test-skeleton
name: check-test-skeleton
entry: uv run --frozen --offline hooks/check-test-skeleton.py
language: system
always_run: true
pass_filenames: false
priority: 0
- id: check-doc-sync
name: check-doc-sync
entry: uv run --frozen --offline hooks/check-doc-sync.py
Expand All @@ -88,8 +93,6 @@ repos:
always_run: true
pass_filenames: false
priority: 0
- repo: local
hooks:
- id: export-module-tree
name: export-module-tree
entry: uv run --frozen --offline hooks/export-module-tree.py
Expand Down
67 changes: 67 additions & 0 deletions hooks/check-test-skeleton.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"""Check that every test file has a matching source module.

For each tests/usethis/**/test_*.py file, at least one of the following source
paths must exist under src/usethis/:

- Direct name match (test_foo.py -> foo.py)
- Underscore-prefixed match (test_foo.py -> _foo.py)
- Parent-stripped match (test_parent_foo.py -> foo.py)
- Underscore parent-stripped match (test_parent_foo.py -> _foo.py)
"""

from __future__ import annotations

import sys
from pathlib import Path

TESTS_DIR = Path("tests/usethis")
SRC_DIR = Path("src")


def main() -> int:
if not TESTS_DIR.is_dir():
print(f"ERROR: {TESTS_DIR} directory not found.", file=sys.stderr)
return 1

errors: list[str] = []

for test_py in sorted(TESTS_DIR.rglob("test_*.py")):
path = SRC_DIR / test_py.relative_to("tests")
std_path = path.parent / path.name.removeprefix("test_")
underscore_path = path.parent / ("_" + path.name.removeprefix("test_"))
parent_prefix = "test_" + path.parent.name.strip("_") + "_"
std_parent_path = path.parent / path.name.removeprefix(parent_prefix)
underscore_parent_path = path.parent / (
"_" + path.name.removeprefix(parent_prefix)
)

if (
not std_path.exists()
and not underscore_path.exists()
and not std_parent_path.exists()
and not underscore_parent_path.exists()
):
errors.append(
f" {test_py}\n"
f" Expected one of:\n"
f" {std_path}\n"
f" {underscore_path}\n"
f" {std_parent_path}\n"
f" {underscore_parent_path}"
)

if errors:
print(
"ERROR: The following test files have no matching source module:",
file=sys.stderr,
)
for error in errors:
print(error, file=sys.stderr)
return 1

print("All test files have matching source modules.")
return 0


if __name__ == "__main__":
raise SystemExit(main())
33 changes: 0 additions & 33 deletions tests/test_suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,39 +7,6 @@ class PytestSuiteConfigurationError(Exception):
pass


def test_skeleton_matches():
# If a tests/usethis/**/test_*.py exists, it should have a matching module named
# src/usethis/**/*.py

for test_py in Path("tests/usethis").rglob("test_*.py"):
path = Path("src") / test_py.relative_to("tests")
std_path = path.parent / path.name.removeprefix("test_")
underscore_path = path.parent / ("_" + path.name.removeprefix("test_"))
std_parent_path = path.parent / path.name.removeprefix(
"test_" + path.parent.name.strip("_") + "_"
)
underscore_parent_path = path.parent / (
"_" + path.name.removeprefix("test_" + path.parent.name.strip("_") + "_")
)

if (
not std_path.exists()
and not underscore_path.exists()
and not std_parent_path.exists()
and not underscore_parent_path.exists()
):
msg = (
f"Since this test file exists:"
f"\n{test_py}"
f"One of the following paths is expected to exist:"
f"\n{std_path}"
f"\n{underscore_path}"
f"\n{std_parent_path}"
f"\n{underscore_parent_path}"
)
raise PytestSuiteConfigurationError(msg)


def test_uv_init_not_git_repo(uv_init_dir: Path):
# We shouldn't be in a git repo when running uv_init_dir, only uv_init_repo_dir
# should be in a git repo
Expand Down
Loading