diff --git a/src/mutahunter/core/entities/mutant.py b/src/mutahunter/core/entities/mutant.py index ef19fa4..0c47022 100644 --- a/src/mutahunter/core/entities/mutant.py +++ b/src/mutahunter/core/entities/mutant.py @@ -10,3 +10,4 @@ class Mutant: status: Union[None, str] = None error_msg: str = "" test_file_path: str = "" + diff: str = "" diff --git a/src/mutahunter/core/hunter.py b/src/mutahunter/core/hunter.py index f7e9e17..b89e977 100644 --- a/src/mutahunter/core/hunter.py +++ b/src/mutahunter/core/hunter.py @@ -94,18 +94,25 @@ def should_skip_file(self, filename: str) -> bool: Returns: bool: True if the file should be skipped, False otherwise. """ - if ( - self.config["only_mutate_file_paths"] - and filename not in self.config["only_mutate_file_paths"] - ): - return True - if filename in self.config["exclude_files"]: - return True - if any( - keyword in filename - for keyword in ["test/", "tests/", "test_", "_test", ".test"] - ): - return True + if self.config["only_mutate_file_paths"]: + # NOTE: Check if the file exists before proceeding. + for file_path in self.config["only_mutate_file_paths"]: + if not os.path.exists(file_path): + logger.error(f"File {file_path} does not exist.") + raise FileNotFoundError(f"File {file_path} does not exist.") + # NOTE: Only mutate the files specified in the config. + if filename in self.config["only_mutate_file_paths"]: + return False + else: + return True + else: + if filename in self.config["exclude_files"]: + return True + if any( + keyword in filename + for keyword in ["test/", "tests/", "test_", "_test", ".test"] + ): + return True return False def generate_mutations(self) -> Generator[Dict[str, Any], None, None]: @@ -169,8 +176,10 @@ def run_mutation_testing(self) -> None: end_byte=mutant_data["end_byte"], mutant_code=mutant_data["mutant_code_snippet"], ) + unified_diff = "".join(mutant_data["hunk"]) mutant = Mutant( id=mutant_id, + diff=unified_diff, source_path=mutant_data["source_path"], mutant_path=mutant_path, test_file_path=mutant_data["test_file_path"], diff --git a/src/mutahunter/core/pilot/prompts/user.py b/src/mutahunter/core/pilot/prompts/user.py index 624bc93..263a942 100644 --- a/src/mutahunter/core/pilot/prompts/user.py +++ b/src/mutahunter/core/pilot/prompts/user.py @@ -18,29 +18,7 @@ # Task: 1. Read the Abstract Syntax Tree of the source code to understand its context. -2. Analyze the provided function block. -3. Introduce a mutation using one of the following mutation operators: - -AOD - arithmetic operator deletion -AOR - arithmetic operator replacement -ASR - assignment operator replacement -BCR - break continue replacement -COD - conditional operator deletion -COI - conditional operator insertion -CRP - constant replacement -DDL - decorator deletion -EHD - exception handler deletion -EXS - exception swallowing -IHD - hiding variable deletion -IOD - overriding method deletion -IOP - overridden method calling position change -LCR - logical connector replacement -LOD - logical operator deletion -LOR - logical operator replacement -ROR - relational operator replacement -SCD - super calling deletion -SCI - super calling insert -SIR - slice index remove +2. Analyze the provided function block to identify a mutation that will test the robustness of the test suite. Your output must follow the format below: 1. Return the full function block with the mutation included. diff --git a/tests/test_hunter.py b/tests/test_hunter.py index 517d13f..c1b5cc2 100644 --- a/tests/test_hunter.py +++ b/tests/test_hunter.py @@ -97,15 +97,6 @@ def test_generate_mutations_skips_files_in_exclude_files(mutant_hunter, config): assert len(mutations) == 0 -def test_generate_mutations_skips_files_not_in_only_mutate_file_paths( - mutant_hunter, config -): - config["only_mutate_file_paths"] = ["file2.py"] - mutant_hunter.analyzer.file_lines_executed = {"file1.py": [1, 2, 3]} - mutations = list(mutant_hunter.generate_mutations()) - assert len(mutations) == 0 - - @patch("mutahunter.core.hunter.logger") def test_run_handles_exceptions(mock_logger, mutant_hunter): with patch.object( diff --git a/tests/test_report.py b/tests/test_report.py index d7da0b5..9b4e720 100644 --- a/tests/test_report.py +++ b/tests/test_report.py @@ -17,6 +17,7 @@ def mutants(): status="KILLED", error_msg="", test_file_path="app_test.go", + diff="", ), Mutant( id="2", @@ -25,6 +26,7 @@ def mutants(): status="SURVIVED", error_msg="", test_file_path="app_test.go", + diff="", ), Mutant( id="3", @@ -33,6 +35,7 @@ def mutants(): status="KILLED", error_msg="", test_file_path="app_test.go", + diff="", ), Mutant( id="4", @@ -41,6 +44,7 @@ def mutants(): status="SURVIVED", error_msg="", test_file_path="app_test.go", + diff="", ), ] @@ -127,6 +131,7 @@ def test_generate_survived_mutants(mutants): "status": "SURVIVED", "error_msg": "", "test_file_path": "app_test.go", + "diff": "", }, { "id": "4", @@ -135,6 +140,7 @@ def test_generate_survived_mutants(mutants): "status": "SURVIVED", "error_msg": "", "test_file_path": "app_test.go", + "diff": "", }, ] @@ -155,6 +161,7 @@ def test_generate_killed_mutants(mutants): "status": "KILLED", "error_msg": "", "test_file_path": "app_test.go", + "diff": "", }, { "id": "3", @@ -163,5 +170,6 @@ def test_generate_killed_mutants(mutants): "status": "KILLED", "error_msg": "", "test_file_path": "app_test.go", + "diff": "", }, ]