-
Notifications
You must be signed in to change notification settings - Fork 4
perf: Cache or narrow TestSuiteGate test discovery (avoid full rglob … #159
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,6 +20,8 @@ class TestSuiteGate(BaseCheck): | |
|
|
||
| def __init__(self, project_root: Optional[Path] = None): | ||
| self.project_root = project_root | ||
| self._test_file_cache: Optional[Dict[str, List[Path]]] = None | ||
| self._all_test_files: Optional[List[Path]] = None | ||
|
|
||
| def verify(self, original: str, transformed: str, file_path: Path) -> CheckResult: | ||
| start = time.monotonic() | ||
|
|
@@ -110,11 +112,27 @@ def _find_relevant_tests(self, file_path: Path) -> List[Path]: | |
| module_name = file_path.stem | ||
| search_root = self.project_root or file_path.parent | ||
|
Comment on lines
112
to
113
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cache key should include module path, not only file stem. At Line 112, using Proposed fix module_name = file_path.stem
+ module_cache_key = str(file_path.resolve())
search_root = self.project_root or file_path.parent
@@
- if module_name in self._test_file_cache:
- return self._test_file_cache[module_name]
+ if module_cache_key in self._test_file_cache:
+ return self._test_file_cache[module_cache_key]
@@
- self._test_file_cache[module_name] = test_files
+ self._test_file_cache[module_cache_key] = test_files
return test_filesAlso applies to: 131-132, 145-146 🤖 Prompt for AI Agents |
||
|
|
||
| if self._test_file_cache is None: | ||
| self._test_file_cache = {} | ||
| self._all_test_files = [] | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove trailing whitespace to unblock pre-commit. Lines around Line 118/122/130/144 include trailing spaces, and pre-commit already failed on this hook. Also applies to: 122-122, 130-130, 144-144 🤖 Prompt for AI Agents |
||
| test_dirs = [d for d in [search_root / "tests", search_root / "test"] if d.is_dir()] | ||
| search_dirs = test_dirs if test_dirs else [search_root] | ||
|
Comment on lines
+119
to
+120
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Discovery narrowing can miss valid tests in mixed layouts. At Line 120, when Safer fallback pattern (keep fast path, avoid false negatives) test_dirs = [d for d in [search_root / "tests", search_root / "test"] if d.is_dir()]
search_dirs = test_dirs if test_dirs else [search_root]
@@
test_files: List[Path] = []
for py_file in self._all_test_files: # type: ignore
@@
if self._imports_module(source, module_name):
test_files.append(py_file)
except Exception:
continue
+
+ # Mixed-layout fallback: if canonical test dirs exist but yielded nothing relevant,
+ # do one broader pass to catch colocated tests.
+ if not test_files and test_dirs:
+ for py_file in search_root.rglob("*.py"):
+ if any(excluded in py_file.parts for excluded in excluded_dirs):
+ continue
+ name = py_file.name
+ if not (name.startswith("test_") or name.endswith("_test.py")):
+ continue
+ try:
+ source = py_file.read_text(encoding="utf-8")
+ if self._imports_module(source, module_name):
+ test_files.append(py_file)
+ except Exception:
+ continue🤖 Prompt for AI Agents |
||
| excluded_dirs = {".git", ".rag", "__pycache__", "venv", ".venv", "env", "node_modules"} | ||
|
|
||
| for root_dir in search_dirs: | ||
| for py_file in root_dir.rglob("*.py"): | ||
| if any(excluded in py_file.parts for excluded in excluded_dirs): | ||
| continue | ||
| name = py_file.name | ||
| if name.startswith("test_") or name.endswith("_test.py"): | ||
| self._all_test_files.append(py_file) | ||
|
|
||
| if module_name in self._test_file_cache: | ||
| return self._test_file_cache[module_name] | ||
|
|
||
| test_files: List[Path] = [] | ||
| for py_file in search_root.rglob("*.py"): | ||
| name = py_file.name | ||
| if not (name.startswith("test_") or name.endswith("_test.py")): | ||
| continue | ||
| for py_file in self._all_test_files: # type: ignore | ||
| if py_file == file_path: | ||
| continue | ||
| try: | ||
|
|
@@ -123,6 +141,8 @@ def _find_relevant_tests(self, file_path: Path) -> List[Path]: | |
| test_files.append(py_file) | ||
| except Exception: | ||
| continue | ||
|
|
||
| self._test_file_cache[module_name] = test_files | ||
| return test_files | ||
|
|
||
| @staticmethod | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Add explicit
-> Noneon__init__to satisfy typed-def policy.At Line 21,
__init__is missing an explicit return type, which violates the typed-def rule underrefactron/.Proposed fix
As per coding guidelines, "Type annotations are required in refactron/ with mypy disallow_untyped_defs = true enabled."
📝 Committable suggestion
🤖 Prompt for AI Agents