fix: update tests for consolidated CST discovery behavior

Nested functions are now skipped by FunctionVisitor, and
discover_functions no longer swallows parse/IO errors — callers
handle them. Update test expectations accordingly.
This commit is contained in:
Kevin Turcios 2026-02-27 12:08:42 -05:00
parent 47f420214e
commit 91cf6ea2aa
3 changed files with 27 additions and 55 deletions

View file

@ -243,7 +243,6 @@ def _find_all_functions_via_language_support(file_path: Path) -> dict[Path, list
try:
lang_support = get_language_support(file_path)
criteria = FunctionFilterCriteria(require_return=True)
# discover_functions already returns FunctionToOptimize objects
functions[file_path] = lang_support.discover_functions(file_path, criteria)
except Exception as e:
logger.debug(f"Failed to discover functions in {file_path}: {e}")

View file

@ -440,32 +440,23 @@ class TestDiscoverFunctionsParity:
assert js_sync.is_async is False, "JavaScript sync function should have is_async=False"
def test_nested_functions_discovery(self, python_support, js_support):
"""Both should discover nested functions with parent info."""
"""Python skips nested functions; JavaScript discovers them with parent info."""
py_file = write_temp_file(NESTED_FUNCTIONS.python, ".py")
js_file = write_temp_file(NESTED_FUNCTIONS.javascript, ".js")
py_funcs = python_support.discover_functions(py_file)
js_funcs = js_support.discover_functions(js_file)
# Both should find 2 functions (outer and inner)
assert len(py_funcs) == 2, f"Python found {len(py_funcs)}, expected 2"
# Python skips nested functions — only outer is discovered
assert len(py_funcs) == 1, f"Python found {len(py_funcs)}, expected 1"
assert py_funcs[0].function_name == "outer"
# JavaScript discovers both
assert len(js_funcs) == 2, f"JavaScript found {len(js_funcs)}, expected 2"
# Check names
py_names = {f.function_name for f in py_funcs}
js_names = {f.function_name for f in js_funcs}
assert py_names == {"outer", "inner"}, f"Python found {py_names}"
assert js_names == {"outer", "inner"}, f"JavaScript found {js_names}"
# Check parent info for inner function
py_inner = next(f for f in py_funcs if f.function_name == "inner")
js_inner = next(f for f in js_funcs if f.function_name == "inner")
assert len(py_inner.parents) >= 1, "Python inner should have parent info"
assert py_inner.parents[0].name == "outer", "Python inner's parent should be outer"
# JavaScript nested function parent check
assert len(js_inner.parents) >= 1, "JavaScript inner should have parent info"
assert js_inner.parents[0].name == "outer", "JavaScript inner's parent should be outer"
@ -554,11 +545,11 @@ class TestDiscoverFunctionsParity:
assert js_funcs[0].function_name == "standalone"
def test_nonexistent_file_returns_empty(self, python_support, js_support):
"""Both should return empty list for nonexistent files."""
py_funcs = python_support.discover_functions(Path("/nonexistent/file.py"))
js_funcs = js_support.discover_functions(Path("/nonexistent/file.js"))
"""Python raises on nonexistent files; JavaScript returns empty list."""
with pytest.raises(FileNotFoundError):
python_support.discover_functions(Path("/nonexistent/file.py"))
assert py_funcs == []
js_funcs = js_support.discover_functions(Path("/nonexistent/file.js"))
assert js_funcs == []
def test_line_numbers_captured(self, python_support, js_support):

View file

@ -137,7 +137,7 @@ def sync_function():
assert sync_func.is_async is False
def test_discover_nested_functions(self, python_support):
"""Test discovering nested functions."""
"""Test that nested functions are excluded — only top-level and class-level functions are discovered."""
with tempfile.NamedTemporaryFile(suffix=".py", mode="w", delete=False) as f:
f.write("""
def outer():
@ -149,16 +149,9 @@ def outer():
functions = python_support.discover_functions(Path(f.name))
# Both outer and inner should be discovered
assert len(functions) == 2
names = {func.function_name for func in functions}
assert names == {"outer", "inner"}
# Inner should have outer as parent
inner = next(f for f in functions if f.function_name == "inner")
assert len(inner.parents) == 1
assert inner.parents[0].name == "outer"
assert inner.parents[0].type == "FunctionDef"
# Only outer should be discovered; inner is nested and skipped
assert len(functions) == 1
assert functions[0].function_name == "outer"
def test_discover_static_method(self, python_support):
"""Test discovering static methods."""
@ -237,19 +230,21 @@ def func2():
assert func2.starting_line == 4
assert func2.ending_line == 7
def test_discover_invalid_file_returns_empty(self, python_support):
"""Test that invalid Python file returns empty list."""
def test_discover_invalid_file_raises(self, python_support):
"""Test that invalid Python file raises a parse error."""
from libcst._exceptions import ParserSyntaxError
with tempfile.NamedTemporaryFile(suffix=".py", mode="w", delete=False) as f:
f.write("this is not valid python {{{{")
f.flush()
functions = python_support.discover_functions(Path(f.name))
assert functions == []
with pytest.raises(ParserSyntaxError):
python_support.discover_functions(Path(f.name))
def test_discover_nonexistent_file_returns_empty(self, python_support):
"""Test that nonexistent file returns empty list."""
functions = python_support.discover_functions(Path("/nonexistent/file.py"))
assert functions == []
def test_discover_nonexistent_file_raises(self, python_support):
"""Test that nonexistent file raises FileNotFoundError."""
with pytest.raises(FileNotFoundError):
python_support.discover_functions(Path("/nonexistent/file.py"))
class TestReplaceFunction:
@ -584,12 +579,7 @@ def process(value):
return helper_function(value) + 1
""")
func = FunctionToOptimize(
function_name="helper_function",
file_path=source_file,
starting_line=1,
ending_line=2,
)
func = FunctionToOptimize(function_name="helper_function", file_path=source_file, starting_line=1, ending_line=2)
refs = python_support.find_references(func, project_root=tmp_path)
@ -646,12 +636,7 @@ def test_find_references_no_references(python_support, tmp_path):
return 42
""")
func = FunctionToOptimize(
function_name="isolated_function",
file_path=source_file,
starting_line=1,
ending_line=2,
)
func = FunctionToOptimize(function_name="isolated_function", file_path=source_file, starting_line=1, ending_line=2)
refs = python_support.find_references(func, project_root=tmp_path)
@ -668,10 +653,7 @@ def test_find_references_nonexistent_function(python_support, tmp_path):
""")
func = FunctionToOptimize(
function_name="nonexistent_function",
file_path=source_file,
starting_line=1,
ending_line=2,
function_name="nonexistent_function", file_path=source_file, starting_line=1, ending_line=2
)
refs = python_support.find_references(func, project_root=tmp_path)