Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
cdc2a4b
fix: JUnit version detection for multi-module Maven projects
mashraf-222 Feb 19, 2026
06382ea
fix: Add path caching for test file resolution in benchmarks
mashraf-222 Feb 19, 2026
c7b4534
fix: Handle complex expressions in Java test instrumentation
mashraf-222 Feb 19, 2026
90afeda
fix: Direct JVM execution for multi-module Maven projects
mashraf-222 Feb 19, 2026
54e0b38
fix: set perf_stdout for Java performance tests to fix throughput cal…
mashraf-222 Feb 19, 2026
0001fb5
fix: store actual test method name in SQLite for Java behavior tests
mashraf-222 Feb 20, 2026
6220ace
chore: auto-format lint fixes from pre-commit
mashraf-222 Feb 20, 2026
6113bac
fix: add JUnit Console Standalone to classpath for direct JVM execution
mashraf-222 Feb 20, 2026
a3f5943
fix: cache TestConfig.test_framework to avoid repeated pom.xml parsing
mashraf-222 Feb 20, 2026
bb6f38f
fix: detect JUnit version from classpath strings instead of subproces…
mashraf-222 Feb 20, 2026
d860857
fix: JUnit version detection for multi-module Maven projects
mashraf-222 Feb 19, 2026
b6564e6
style: auto-fix linting issues
github-actions[bot] Feb 20, 2026
cfcbd92
fix: correct JUnit version logging for projects using ConsoleLauncher…
mashraf-222 Feb 20, 2026
d54aa68
Apply suggestion from @claude[bot]
misrasaurabh1 Feb 20, 2026
53528a2
style: auto-fix linting issues
github-actions[bot] Feb 20, 2026
b8ec235
fix: resolve mypy type errors in Java config and instrumentation
github-actions[bot] Feb 20, 2026
58561c8
coverage reported correctly
misrasaurabh1 Feb 20, 2026
8a1ab8e
fix pr creation bug
misrasaurabh1 Feb 20, 2026
96d94cd
Optimize _add_behavior_instrumentation
codeflash-ai[bot] Feb 20, 2026
864f87f
style: merge multiple comparisons per PLR1714
github-actions[bot] Feb 20, 2026
648a613
Optimize _add_timing_instrumentation
codeflash-ai[bot] Feb 20, 2026
a523c9a
style: auto-fix linting issues
github-actions[bot] Feb 20, 2026
75762bd
Optimize _is_inside_lambda
codeflash-ai[bot] Feb 20, 2026
2c0e1d9
Optimize _byte_to_line_index
codeflash-ai[bot] Feb 20, 2026
4294601
style: auto-fix linting issues
github-actions[bot] Feb 20, 2026
06dfb96
fix: implement Java process_review methods to prevent crash after opt…
mashraf-222 Feb 20, 2026
f06acba
fix: add test method name to Java stdout markers for unique identific…
mashraf-222 Feb 20, 2026
d4add61
fix: clear test file path cache between optimization iterations in --…
mashraf-222 Feb 20, 2026
38d6309
chore: log debug message when JUnitCore ignores reports_dir parameter
mashraf-222 Feb 20, 2026
5346cab
style: auto-fix linting issues
github-actions[bot] Feb 20, 2026
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
99 changes: 71 additions & 28 deletions codeflash/languages/java/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,16 +152,20 @@ def _detect_test_framework(project_root: Path, build_tool: BuildTool) -> tuple[s
except Exception:
pass

# Determine primary framework (prefer JUnit 5)
# Determine primary framework (prefer JUnit 5 if explicitly found)
if has_junit5:
logger.debug("Selected JUnit 5 as test framework")
return "junit5", has_junit5, has_junit4, has_testng
if has_junit4:
logger.debug("Selected JUnit 4 as test framework")
return "junit4", has_junit5, has_junit4, has_testng
if has_testng:
logger.debug("Selected TestNG as test framework")
return "testng", has_junit5, has_junit4, has_testng

# Default to JUnit 5 if nothing detected
return "junit5", has_junit5, has_junit4, has_testng
# Default to JUnit 4 if nothing detected (more common in legacy projects)
logger.debug("No test framework detected, defaulting to JUnit 4")
return "junit4", has_junit5, has_junit4, has_testng


def _detect_test_deps_from_pom(project_root: Path) -> tuple[bool, bool, bool]:
Expand All @@ -179,42 +183,81 @@ def _detect_test_deps_from_pom(project_root: Path) -> tuple[bool, bool, bool]:
has_junit4 = False
has_testng = False

def check_dependencies(deps_element: ET.Element | None, ns: dict[str, str]) -> None:
"""Check dependencies element for test frameworks."""
nonlocal has_junit5, has_junit4, has_testng

if deps_element is None:
return

for dep_path in ["dependency", "m:dependency"]:
deps_list = deps_element.findall(dep_path, ns) if "m:" in dep_path else deps_element.findall(dep_path)
for dep in deps_list:
artifact_id = None
group_id = None

for child in dep:
tag = child.tag.replace("{http://maven.apache.org/POM/4.0.0}", "")
if tag == "artifactId":
artifact_id = child.text
elif tag == "groupId":
group_id = child.text

if group_id == "org.junit.jupiter" or (artifact_id and "junit-jupiter" in artifact_id):
has_junit5 = True
logger.debug("Found JUnit 5 dependency: %s:%s", group_id, artifact_id)
elif group_id == "junit" and artifact_id == "junit":
has_junit4 = True
logger.debug("Found JUnit 4 dependency: %s:%s", group_id, artifact_id)
elif group_id == "org.testng":
has_testng = True
logger.debug("Found TestNG dependency: %s:%s", group_id, artifact_id)

try:
tree = ET.parse(pom_path)
root = tree.getroot()

# Handle namespace
ns = {"m": "http://maven.apache.org/POM/4.0.0"}

# Search for dependencies
logger.debug("Checking pom.xml at %s", pom_path)

# Search for direct dependencies
for deps_path in ["dependencies", "m:dependencies"]:
deps = root.find(deps_path, ns) if "m:" in deps_path else root.find(deps_path)
if deps is None:
continue

for dep_path in ["dependency", "m:dependency"]:
deps_list = deps.findall(dep_path, ns) if "m:" in dep_path else deps.findall(dep_path)
for dep in deps_list:
artifact_id = None
group_id = None

for child in dep:
tag = child.tag.replace("{http://maven.apache.org/POM/4.0.0}", "")
if tag == "artifactId":
artifact_id = child.text
elif tag == "groupId":
group_id = child.text

if group_id == "org.junit.jupiter" or (artifact_id and "junit-jupiter" in artifact_id):
has_junit5 = True
elif group_id == "junit" and artifact_id == "junit":
has_junit4 = True
elif group_id == "org.testng":
has_testng = True
if deps is not None:
logger.debug("Found dependencies section in %s", pom_path)
check_dependencies(deps, ns)

# Also check dependencyManagement section (for multi-module projects)
for dep_mgmt_path in ["dependencyManagement", "m:dependencyManagement"]:
dep_mgmt = root.find(dep_mgmt_path, ns) if "m:" in dep_mgmt_path else root.find(dep_mgmt_path)
if dep_mgmt is not None:
logger.debug("Found dependencyManagement section in %s", pom_path)
for deps_path in ["dependencies", "m:dependencies"]:
deps = dep_mgmt.find(deps_path, ns) if "m:" in deps_path else dep_mgmt.find(deps_path)
if deps is not None:
check_dependencies(deps, ns)

except ET.ParseError:
pass

logger.debug("Failed to parse pom.xml at %s", pom_path)

# For multi-module projects, also check submodule pom.xml files
if not (has_junit5 or has_junit4 or has_testng):
logger.debug("No test deps in root pom, checking submodules")
# Check common submodule locations
for submodule_name in ["test", "tests", "src/test", "testing"]:
submodule_pom = project_root / submodule_name / "pom.xml"
if submodule_pom.exists():
logger.debug("Checking submodule pom at %s", submodule_pom)
sub_junit5, sub_junit4, sub_testng = _detect_test_deps_from_pom(project_root / submodule_name)
Comment on lines 248 to 253
Copy link
Contributor

@claude claude bot Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Resolved — the recursion is now bounded to specific hardcoded directory names (["test", "tests", "src/test", "testing"]) with early break on first match. Practical recursion depth is at most 1 level.

has_junit5 = has_junit5 or sub_junit5
has_junit4 = has_junit4 or sub_junit4
has_testng = has_testng or sub_testng
if has_junit5 or has_junit4 or has_testng:
break

logger.debug("Test framework detection result: junit5=%s, junit4=%s, testng=%s", has_junit5, has_junit4, has_testng)
return has_junit5, has_junit4, has_testng


Expand Down
Loading
Loading