fix: set tests_project_rootdir to tests_root for Java projects

Bug #2: Test file name mapping returns null for Java tests

Root cause: For Java projects, tests_project_rootdir was incorrectly set
to the project root instead of the actual tests directory. This caused
test file resolution to fail in parse_test_xml when parsing JUnit XML
from Maven Surefire, which doesn't include file attributes.

JavaScript already had this fix (line 654), but Java was missing it.

Fix: Add Java to the language check that sets tests_project_rootdir
equal to tests_root, ensuring instrumented test files can be found at
src/test/java/com/example/Test__perfinstrumented.java

Changes:
- Added is_java import to discover_unit_tests.py
- Added Java check: if is_java(): cfg.tests_project_rootdir = cfg.tests_root
- Added comprehensive test coverage with 2 test cases

Tests:
- test_java_tests_project_rootdir_set_to_tests_root: verifies fix for Java
- test_python_tests_project_rootdir_unchanged: verifies Python unchanged

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Mohamed Ashraf 2026-02-04 00:04:23 +00:00
parent 7b72a7e6ad
commit a582fa6ea8
2 changed files with 87 additions and 2 deletions

View file

@ -641,17 +641,20 @@ def discover_unit_tests(
discover_only_these_tests: list[Path] | None = None,
file_to_funcs_to_optimize: dict[Path, list[FunctionToOptimize]] | None = None,
) -> tuple[dict[str, set[FunctionCalledInTest]], int, int]:
from codeflash.languages import is_javascript, is_python
from codeflash.languages import is_java, is_javascript, is_python
# Detect language from functions being optimized
language = _detect_language_from_functions(file_to_funcs_to_optimize)
# Route to language-specific test discovery for non-Python languages
if not is_python():
# For JavaScript/TypeScript, tests_project_rootdir should be tests_root itself
# For JavaScript/TypeScript and Java, tests_project_rootdir should be tests_root itself
# The Jest helper will be configured to NOT include "tests." prefix to match
# For Java, this ensures test file resolution works correctly in parse_test_xml
if is_javascript():
cfg.tests_project_rootdir = cfg.tests_root
if is_java():
cfg.tests_project_rootdir = cfg.tests_root
return discover_tests_for_language(cfg, language, file_to_funcs_to_optimize)
# Existing Python logic

View file

@ -0,0 +1,82 @@
"""Test that tests_project_rootdir is set correctly for Java projects."""
from pathlib import Path
from unittest.mock import MagicMock, patch
from codeflash.discovery.discover_unit_tests import discover_unit_tests
from codeflash.languages.base import Language
from codeflash.languages.current import set_current_language
from codeflash.verification.verification_utils import TestConfig
def test_java_tests_project_rootdir_set_to_tests_root(tmp_path):
"""Test that for Java projects, tests_project_rootdir is set to tests_root."""
# Create a mock Java project structure
project_root = tmp_path / "project"
project_root.mkdir()
(project_root / "pom.xml").touch()
tests_root = project_root / "src" / "test" / "java"
tests_root.mkdir(parents=True)
# Create test config with tests_project_rootdir initially set to project root
# (simulating what happens before the fix)
test_cfg = TestConfig(
tests_root=tests_root,
project_root_path=project_root,
tests_project_rootdir=project_root, # Initially set to project root
)
# Create a mock Java function to ensure language detection works
mock_java_function = MagicMock()
mock_java_function.language = "java"
file_to_funcs = {Path("dummy.java"): [mock_java_function]}
# Mock is_python() to return False and is_java() to return True
# These are imported from codeflash.languages
with patch("codeflash.languages.is_python", return_value=False), \
patch("codeflash.languages.is_java", return_value=True), \
patch("codeflash.discovery.discover_unit_tests.discover_tests_for_language") as mock_discover:
mock_discover.return_value = ({}, 0, 0)
# Call discover_unit_tests
discover_unit_tests(test_cfg, file_to_funcs_to_optimize=file_to_funcs)
# Verify that tests_project_rootdir was updated to tests_root
assert test_cfg.tests_project_rootdir == tests_root, (
f"Expected tests_project_rootdir to be {tests_root}, "
f"but got {test_cfg.tests_project_rootdir}"
)
def test_python_tests_project_rootdir_unchanged(tmp_path):
"""Test that for Python projects, tests_project_rootdir behavior is unchanged."""
# Setup Python environment
set_current_language(Language.PYTHON)
# Create a mock Python project structure
project_root = tmp_path / "project"
project_root.mkdir()
(project_root / "pyproject.toml").touch()
tests_root = project_root / "tests"
tests_root.mkdir()
# Create test config
original_tests_project_rootdir = project_root / "some" / "other" / "dir"
test_cfg = TestConfig(
tests_root=tests_root,
project_root_path=project_root,
tests_project_rootdir=original_tests_project_rootdir,
)
# Mock pytest discovery
with patch("codeflash.discovery.discover_unit_tests.discover_tests_pytest") as mock_discover:
mock_discover.return_value = ({}, 0, 0)
# Call discover_unit_tests
discover_unit_tests(test_cfg, file_to_funcs_to_optimize={})
# For Python, tests_project_rootdir should remain unchanged
# (the function doesn't modify it for Python projects)
assert test_cfg.tests_project_rootdir == original_tests_project_rootdir