From 3541bd9165a29f4ad68abcaea9c0cbb0ccbbab4a Mon Sep 17 00:00:00 2001 From: Mohamed Ashraf Date: Fri, 16 Jan 2026 18:03:25 +0200 Subject: [PATCH 1/2] FIX: --no-gen-tests Flag Causes Path Resolution Error with Module-Root --- codeflash/models/models.py | 67 ++++++++++++++++++++- codeflash/verification/parse_test_output.py | 7 ++- 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/codeflash/models/models.py b/codeflash/models/models.py index 133299589..0f44f7266 100644 --- a/codeflash/models/models.py +++ b/codeflash/models/models.py @@ -372,21 +372,82 @@ def add(self, test_file: TestFile) -> None: raise ValueError(msg) def get_by_original_file_path(self, file_path: Path) -> TestFile | None: - return next((test_file for test_file in self.test_files if test_file.original_file_path == file_path), None) + # Normalize the input path for comparison + try: + normalized_file_path = file_path.resolve() + except (OSError, RuntimeError): + normalized_file_path = file_path.absolute() + + return next( + ( + test_file + for test_file in self.test_files + if test_file.original_file_path is not None + and self._paths_match(normalized_file_path, test_file.original_file_path, None) + ), + None, + ) def get_test_type_by_instrumented_file_path(self, file_path: Path) -> TestType | None: + # Normalize the input path for comparison + try: + normalized_file_path = file_path.resolve() + except (OSError, RuntimeError): + # If resolve fails (e.g., file doesn't exist), use absolute path + normalized_file_path = file_path.absolute() + return next( ( test_file.test_type for test_file in self.test_files - if (file_path in (test_file.instrumented_behavior_file_path, test_file.benchmarking_file_path)) + if self._paths_match( + normalized_file_path, + test_file.instrumented_behavior_file_path, + test_file.benchmarking_file_path, + ) ), None, ) + + def _paths_match(self, path1: Path, path2: Path | None, path3: Path | None) -> bool: + """Check if path1 matches path2 or path3 after normalization.""" + def normalize_path(path: Path) -> Path: + """Normalize a path for comparison.""" + try: + return path.resolve() + except (OSError, RuntimeError): + # If resolve fails (e.g., file doesn't exist), use absolute path + return path.absolute() + + normalized_path1 = normalize_path(path1) + + if path2 is not None: + normalized_path2 = normalize_path(path2) + # Compare using string representation to handle Windows path case insensitivity + if str(normalized_path1).lower() == str(normalized_path2).lower(): + return True + if path3 is not None: + normalized_path3 = normalize_path(path3) + # Compare using string representation to handle Windows path case insensitivity + if str(normalized_path1).lower() == str(normalized_path3).lower(): + return True + return False def get_test_type_by_original_file_path(self, file_path: Path) -> TestType | None: + # Normalize the input path for comparison + try: + normalized_file_path = file_path.resolve() + except (OSError, RuntimeError): + normalized_file_path = file_path.absolute() + return next( - (test_file.test_type for test_file in self.test_files if test_file.original_file_path == file_path), None + ( + test_file.test_type + for test_file in self.test_files + if test_file.original_file_path is not None + and self._paths_match(normalized_file_path, test_file.original_file_path, None) + ), + None, ) def __iter__(self) -> Iterator[TestFile]: diff --git a/codeflash/verification/parse_test_output.py b/codeflash/verification/parse_test_output.py index d6b529d6d..188d0c57e 100644 --- a/codeflash/verification/parse_test_output.py +++ b/codeflash/verification/parse_test_output.py @@ -316,7 +316,12 @@ def parse_test_xml( logger.warning(f"Could not find the test for file name - {test_file_path} ") continue test_type = test_files.get_test_type_by_instrumented_file_path(test_file_path) - assert test_type is not None, f"Test type not found for {test_file_path}" + if test_type is None: + logger.warning( + f"Test type not found for {test_file_path}. " + f"This may indicate the test file was not properly registered. Skipping test case." + ) + continue test_module_path = module_name_from_file_path(test_file_path, test_config.tests_project_rootdir) result = testcase.is_passed # TODO: See for the cases of ERROR and SKIPPED test_class = None From 3ba5ed394a950d550d7003a47e76238155d7ccf6 Mon Sep 17 00:00:00 2001 From: Mohamed Ashraf Date: Fri, 16 Jan 2026 18:53:09 +0200 Subject: [PATCH 2/2] Refactor path normalization in TestFiles model for consistency and cross-platform compatibility. Remove redundant path matching logic and enhance logging in parse_test_xml for better debugging of test type registration issues. --- codeflash/models/models.py | 72 +++++++-------------- codeflash/verification/parse_test_output.py | 6 +- 2 files changed, 27 insertions(+), 51 deletions(-) diff --git a/codeflash/models/models.py b/codeflash/models/models.py index 0f44f7266..7b0e5e326 100644 --- a/codeflash/models/models.py +++ b/codeflash/models/models.py @@ -372,84 +372,58 @@ def add(self, test_file: TestFile) -> None: raise ValueError(msg) def get_by_original_file_path(self, file_path: Path) -> TestFile | None: - # Normalize the input path for comparison - try: - normalized_file_path = file_path.resolve() - except (OSError, RuntimeError): - normalized_file_path = file_path.absolute() - + normalized = self._normalize_path_for_comparison(file_path) return next( ( test_file for test_file in self.test_files if test_file.original_file_path is not None - and self._paths_match(normalized_file_path, test_file.original_file_path, None) + and normalized == self._normalize_path_for_comparison(test_file.original_file_path) ), None, ) def get_test_type_by_instrumented_file_path(self, file_path: Path) -> TestType | None: - # Normalize the input path for comparison - try: - normalized_file_path = file_path.resolve() - except (OSError, RuntimeError): - # If resolve fails (e.g., file doesn't exist), use absolute path - normalized_file_path = file_path.absolute() - + normalized = self._normalize_path_for_comparison(file_path) return next( ( test_file.test_type for test_file in self.test_files - if self._paths_match( - normalized_file_path, - test_file.instrumented_behavior_file_path, - test_file.benchmarking_file_path, + if normalized == self._normalize_path_for_comparison(test_file.instrumented_behavior_file_path) + or ( + test_file.benchmarking_file_path is not None + and normalized == self._normalize_path_for_comparison(test_file.benchmarking_file_path) ) ), None, ) - - def _paths_match(self, path1: Path, path2: Path | None, path3: Path | None) -> bool: - """Check if path1 matches path2 or path3 after normalization.""" - def normalize_path(path: Path) -> Path: - """Normalize a path for comparison.""" - try: - return path.resolve() - except (OSError, RuntimeError): - # If resolve fails (e.g., file doesn't exist), use absolute path - return path.absolute() - - normalized_path1 = normalize_path(path1) - - if path2 is not None: - normalized_path2 = normalize_path(path2) - # Compare using string representation to handle Windows path case insensitivity - if str(normalized_path1).lower() == str(normalized_path2).lower(): - return True - if path3 is not None: - normalized_path3 = normalize_path(path3) - # Compare using string representation to handle Windows path case insensitivity - if str(normalized_path1).lower() == str(normalized_path3).lower(): - return True - return False def get_test_type_by_original_file_path(self, file_path: Path) -> TestType | None: - # Normalize the input path for comparison - try: - normalized_file_path = file_path.resolve() - except (OSError, RuntimeError): - normalized_file_path = file_path.absolute() - + normalized = self._normalize_path_for_comparison(file_path) return next( ( test_file.test_type for test_file in self.test_files if test_file.original_file_path is not None - and self._paths_match(normalized_file_path, test_file.original_file_path, None) + and normalized == self._normalize_path_for_comparison(test_file.original_file_path) ), None, ) + @staticmethod + def _normalize_path_for_comparison(path: Path) -> str: + """Normalize a path for cross-platform comparison. + + Resolves the path to an absolute path and handles Windows case-insensitivity. + """ + try: + resolved = str(path.resolve()) + except (OSError, RuntimeError): + # If resolve fails (e.g., file doesn't exist), use absolute path + resolved = str(path.absolute()) + # Only lowercase on Windows where filesystem is case-insensitive + return resolved.lower() if sys.platform == "win32" else resolved + def __iter__(self) -> Iterator[TestFile]: return iter(self.test_files) diff --git a/codeflash/verification/parse_test_output.py b/codeflash/verification/parse_test_output.py index 188d0c57e..2cb112221 100644 --- a/codeflash/verification/parse_test_output.py +++ b/codeflash/verification/parse_test_output.py @@ -317,9 +317,11 @@ def parse_test_xml( continue test_type = test_files.get_test_type_by_instrumented_file_path(test_file_path) if test_type is None: + # Log registered paths for debugging + registered_paths = [str(tf.instrumented_behavior_file_path) for tf in test_files.test_files] logger.warning( - f"Test type not found for {test_file_path}. " - f"This may indicate the test file was not properly registered. Skipping test case." + f"Test type not found for '{test_file_path}'. " + f"Registered test files: {registered_paths}. Skipping test case." ) continue test_module_path = module_name_from_file_path(test_file_path, test_config.tests_project_rootdir)