mutant-hunter-env / tests /test_models.py
Krishna1107's picture
Initial commit: MutantHunter — RL env for mutation-score-rewarded test generation
91487c9
from __future__ import annotations
import pytest
from pydantic import ValidationError
from mutant_hunter.models import Action, Mutant, Observation, State, ToolCall, ToolResult
def test_action_tool_call_valid() -> None:
a = Action(kind="tool_call", tool_call=ToolCall(name="run_tests", args={}))
assert a.kind == "tool_call"
def test_action_tool_call_with_test_code_rejected() -> None:
with pytest.raises(ValidationError):
Action(
kind="tool_call",
tool_call=ToolCall(name="run_tests", args={}),
test_code="def test_x(): pass\n",
)
def test_action_submit_requires_test_code() -> None:
with pytest.raises(ValidationError):
Action(kind="submit_tests")
def test_action_submit_empty_test_code_rejected() -> None:
with pytest.raises(ValidationError):
Action(kind="submit_tests", test_code=" \n")
def test_action_submit_with_tool_call_rejected() -> None:
with pytest.raises(ValidationError):
Action(
kind="submit_tests",
tool_call=ToolCall(name="run_tests", args={}),
test_code="def test_x(): pass\n",
)
def test_observation_defaults_round_trip() -> None:
obs = Observation(reward=0.0)
dumped = obs.model_dump()
restored = Observation(**dumped)
assert restored.budget_remaining == 0
assert restored.history == []
def test_state_surviving_le_total_invariant() -> None:
m = Mutant(
mutant_id="ROR-1-0-0",
operator="ROR",
line=1,
column=0,
original="Eq",
mutated="NotEq",
)
with pytest.raises(ValidationError):
State(
repo_path="x",
module_path="m",
full_source="",
full_test_suite="",
surviving_mutants=[m, m, m],
total_mutants=2,
coverage_baseline=0.0,
)
def test_tool_result_truncated_default_false() -> None:
r = ToolResult(tool="read_file", output="hi")
assert r.truncated is False