Skip to content
Open
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
23 changes: 20 additions & 3 deletions codeflash/languages/java/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,9 @@ def _detect_test_framework(project_root: Path, build_tool: BuildTool) -> tuple[s
logger.debug("Selected TestNG as test framework")
return "testng", 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
# Default to JUnit 5 if nothing detected (standard since 2017)
logger.debug("No test framework detected, defaulting to JUnit 5")
return "junit5", has_junit5, has_junit4, has_testng


def _detect_test_deps_from_pom(project_root: Path) -> tuple[bool, bool, bool]:
Expand Down Expand Up @@ -286,6 +286,23 @@ def _detect_test_deps_from_gradle(project_root: Path) -> tuple[bool, bool, bool]
except Exception:
pass

# For multi-module projects, check submodule build files if root has no test deps
if not (has_junit5 or has_junit4 or has_testng):
for sub_gradle in sorted(project_root.glob("*/build.gradle*")):
if sub_gradle.name in ("build.gradle", "build.gradle.kts"):
try:
content = sub_gradle.read_text(encoding="utf-8")
if "junit-jupiter" in content or "useJUnitPlatform" in content:
has_junit5 = True
if "junit:junit" in content:
has_junit4 = True
if "testng" in content.lower():
has_testng = True
if has_junit5:
break # JUnit 5 found, no need to check more
except Exception:
pass

return has_junit5, has_junit4, has_testng


Expand Down
49 changes: 49 additions & 0 deletions tests/test_languages/test_java/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from codeflash.languages.java.build_tools import BuildTool
from codeflash.languages.java.config import (
JavaProjectConfig,
_detect_test_deps_from_gradle,
_detect_test_framework,
detect_java_project,
get_test_class_pattern,
get_test_file_pattern,
Expand Down Expand Up @@ -342,3 +344,50 @@ def test_detect_fixture_project(self, java_fixture_path: Path):
assert config.source_root is not None
assert config.test_root is not None
assert config.has_junit5 is True


class TestGradleSubmoduleDetection:

def test_detect_gradle_junit5_from_submodule(self, tmp_path: Path) -> None:
root = tmp_path.resolve()
# Root build.gradle with no test deps
(root / "build.gradle.kts").write_text("plugins { java }\n", encoding="utf-8")
(root / "settings.gradle.kts").write_text('include("submodule-a")\n', encoding="utf-8")

# Submodule with JUnit 5
sub = root / "submodule-a"
sub.mkdir()
(sub / "build.gradle.kts").write_text(
'dependencies { testImplementation("org.junit.jupiter:junit-jupiter:5.10.0") }\n'
"tasks.withType<Test> { useJUnitPlatform() }\n",
encoding="utf-8",
)

has_junit5, has_junit4, has_testng = _detect_test_deps_from_gradle(root)
assert has_junit5 is True
assert has_junit4 is False
assert has_testng is False

def test_detect_gradle_junit5_from_root(self, tmp_path: Path) -> None:
root = tmp_path.resolve()
(root / "build.gradle").write_text(
"dependencies { testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0' }\n"
"test { useJUnitPlatform() }\n",
encoding="utf-8",
)

has_junit5, has_junit4, has_testng = _detect_test_deps_from_gradle(root)
assert has_junit5 is True
assert has_junit4 is False
assert has_testng is False

def test_default_to_junit5_when_nothing_detected(self, tmp_path: Path) -> None:
root = tmp_path.resolve()
# Empty Gradle project — no test deps anywhere
(root / "build.gradle.kts").write_text("plugins { java }\n", encoding="utf-8")

framework, has_junit5, has_junit4, has_testng = _detect_test_framework(root, BuildTool.GRADLE)
assert framework == "junit5"
assert has_junit5 is False
assert has_junit4 is False
assert has_testng is False
Loading