Skip to content

Commit 9e8c29d

Browse files
committed
fix: include module-level variables and second-degree helpers in testgen helper FQNs
Generated tests were importing symbols like _EXTENSION_REGISTRY from the wrong module because helper_function_names only contained first-degree function/class helpers. The AI had no metadata about where module-level variables lived, causing incorrect import paths and 0% test coverage.
1 parent 47f5887 commit 9e8c29d

3 files changed

Lines changed: 20 additions & 12 deletions

File tree

codeflash/languages/python/context/code_context_extractor.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,7 @@ def get_code_optimization_context(
107107
for qualified_names in helpers_of_fto_qualified_names_dict.values():
108108
qualified_names.update({f"{qn.rsplit('.', 1)[0]}.__init__" for qn in qualified_names if "." in qn})
109109

110-
# Get FunctionSource representation of helpers of helpers of FTO
111-
helpers_of_helpers_dict, _helpers_of_helpers_list = get_function_sources_from_jedi(
110+
helpers_of_helpers_dict, helpers_of_helpers_list = get_function_sources_from_jedi(
112111
helpers_of_fto_qualified_names_dict, project_root_path
113112
)
114113

@@ -186,13 +185,16 @@ def get_code_optimization_context(
186185
code_hash_context = hashing_code_context.markdown
187186
code_hash = hashlib.sha256(code_hash_context.encode("utf-8")).hexdigest()
188187

188+
all_helper_fqns = list({fs.fully_qualified_name for fs in helpers_of_fto_list + helpers_of_helpers_list})
189+
189190
return CodeOptimizationContext(
190191
testgen_context=testgen_context,
191192
read_writable_code=final_read_writable_code,
192193
read_only_context_code=read_only_context_code,
193194
hashing_code_context=code_hash_context,
194195
hashing_code_context_hash=code_hash,
195196
helper_functions=helpers_of_fto_list,
197+
testgen_helper_fqns=all_helper_fqns,
196198
preexisting_objects=preexisting_objects,
197199
)
198200

@@ -317,13 +319,12 @@ def get_code_optimization_context_for_language(
317319
return CodeOptimizationContext(
318320
testgen_context=testgen_context,
319321
read_writable_code=read_writable_code,
320-
# Pass type definitions and globals as read-only context for the AI
321-
# This way the AI sees them as context but doesn't include them in optimized output
322322
read_only_context_code=code_context.read_only_context,
323323
hashing_code_context=read_writable_code.flat,
324324
hashing_code_context_hash=code_hash,
325325
helper_functions=helper_function_sources,
326-
preexisting_objects=set(), # Not implemented for non-Python yet
326+
testgen_helper_fqns=[fs.fully_qualified_name for fs in helper_function_sources],
327+
preexisting_objects=set(),
327328
)
328329

329330

@@ -519,15 +520,16 @@ def get_function_sources_from_jedi(
519520
and not belongs_to_function_qualified(definition, qualified_function_name)
520521
and definition.full_name.startswith(definition.module_name)
521522
)
522-
if is_valid_definition and definition.type in ("function", "class"):
523+
if is_valid_definition and definition.type in ("function", "class", "statement"):
523524
if definition.type == "function":
524525
fqn = definition.full_name
525526
func_name = definition.name
526-
else:
527-
# When a class is instantiated (e.g., MyClass()), track its __init__ as a helper
528-
# This ensures the class definition with constructor is included in testgen context
527+
elif definition.type == "class":
529528
fqn = f"{definition.full_name}.__init__"
530529
func_name = "__init__"
530+
else:
531+
fqn = definition.full_name
532+
func_name = definition.name
531533
qualified_name = get_qualified_name(definition.module_name, fqn)
532534
# Avoid nested functions or classes. Only class.function is allowed
533535
if len(qualified_name.split(".")) <= 2:

codeflash/models/models.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,7 @@ class CodeOptimizationContext(BaseModel):
380380
hashing_code_context: str = ""
381381
hashing_code_context_hash: str = ""
382382
helper_functions: list[FunctionSource]
383+
testgen_helper_fqns: list[str] = []
383384
preexisting_objects: set[tuple[str, tuple[FunctionParent, ...]]]
384385

385386

codeflash/optimization/function_optimizer.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,7 @@ def generate_and_instrument_tests(
579579
test_results = self.generate_tests(
580580
testgen_context=code_context.testgen_context,
581581
helper_functions=code_context.helper_functions,
582+
testgen_helper_fqns=code_context.testgen_helper_fqns,
582583
generated_test_paths=generated_test_paths,
583584
generated_perf_test_paths=generated_perf_test_paths,
584585
)
@@ -1521,7 +1522,8 @@ def get_code_optimization_context(self) -> Result[CodeOptimizationContext, str]:
15211522
read_only_context_code=new_code_ctx.read_only_context_code,
15221523
hashing_code_context=new_code_ctx.hashing_code_context,
15231524
hashing_code_context_hash=new_code_ctx.hashing_code_context_hash,
1524-
helper_functions=new_code_ctx.helper_functions, # only functions that are read writable
1525+
helper_functions=new_code_ctx.helper_functions,
1526+
testgen_helper_fqns=new_code_ctx.testgen_helper_fqns,
15251527
preexisting_objects=new_code_ctx.preexisting_objects,
15261528
)
15271529
)
@@ -1727,6 +1729,7 @@ def generate_tests(
17271729
self,
17281730
testgen_context: CodeStringsMarkdown,
17291731
helper_functions: list[FunctionSource],
1732+
testgen_helper_fqns: list[str],
17301733
generated_test_paths: list[Path],
17311734
generated_perf_test_paths: list[Path],
17321735
) -> Result[tuple[int, GeneratedTestsList, dict[str, set[FunctionCalledInTest]], str], str]:
@@ -1735,11 +1738,13 @@ def generate_tests(
17351738
assert len(generated_test_paths) == n_tests
17361739

17371740
if not self.args.no_gen_tests:
1738-
# Submit test generation tasks
1741+
helper_fqns = testgen_helper_fqns or [
1742+
definition.fully_qualified_name for definition in helper_functions
1743+
]
17391744
future_tests = self.submit_test_generation_tasks(
17401745
self.executor,
17411746
testgen_context.markdown,
1742-
[definition.fully_qualified_name for definition in helper_functions],
1747+
helper_fqns,
17431748
generated_test_paths,
17441749
generated_perf_test_paths,
17451750
)

0 commit comments

Comments
 (0)