import subprocess import sys from mutator.cli import parse_args, run from mutator.runner import CommandResult def test_lines_option_parses_positive_numbers(): options = parse_args(["--lines", "2, 4", "src/demo.py"]) assert options.lines == {2, 4} def test_changed_selects_a_dirty_source_file(tmp_path, monkeypatch, capsys): path = tmp_path / "src" / "demo.py" path.parent.mkdir() path.write_text("def place(x):\n return x > 0\n", encoding="utf-8") subprocess.run(["git", "init"], cwd=tmp_path, check=True, capture_output=True) subprocess.run(["git", "add", "src/demo.py"], cwd=tmp_path, check=True, capture_output=True) monkeypatch.chdir(tmp_path) code = run(["--scan", "--no-coverage", "--changed", "--root", str(tmp_path)]) captured = capsys.readouterr() assert code == 0 assert "demo.py:2" in captured.out def test_a_directory_argument_skips_a_named_test_file(tmp_path, capsys): src = tmp_path / "pkg" / "app.py" src.parent.mkdir() src.write_text("def place(x):\n return x > 0\n", encoding="utf-8") test = tmp_path / "pkg" / "test_app.py" test.write_text("def test_place():\n assert True\n", encoding="utf-8") code = run( ["--scan", "--no-coverage", "--root", str(tmp_path), str(tmp_path / "pkg"), str(test)] ) captured = capsys.readouterr() assert code == 0 assert "Skipping test file" in captured.err assert "app.py:2" in captured.out def test_help_and_conflicting_flags(): help_options = parse_args(["--help"]) assert help_options.exit_code == 0 assert "uml-viewer" in help_options.message conflict = parse_args(["--mutate-all", "--since-last-run", "src/demo.py"]) assert conflict.exit_code == 1 assert run(["--help"]) == 0 def test_scan_lists_sites_without_writing_metrics(tmp_path, monkeypatch): path = tmp_path / "src" / "demo.py" path.parent.mkdir() path.write_text("def place(x):\n return x > 0\n", encoding="utf-8") monkeypatch.chdir(tmp_path) code = run(["--scan", "--no-coverage", "--root", str(tmp_path), "src/demo.py"]) assert code == 0 assert not (tmp_path / ".metrics").exists() def test_real_python_mutants_update_the_snapshot(tmp_path, capsys): path = tmp_path / "src" / "demo.py" path.parent.mkdir() path.write_text( "def add(a, b):\n" " if a > 0:\n" " return a + b\n" " return 0\n", encoding="utf-8", ) command = ( f"{sys.executable} -c \"import sys; sys.path.insert(0, 'src'); " "from demo import add; raise SystemExit(0 if add(2, 3) == 5 else 1)\"" ) code = run( [ "--no-coverage", "--mutate-all", "--root", str(tmp_path), "--test-command", command, "src/demo.py", ] ) captured = capsys.readouterr() assert code == 3 assert "SURVIVED" in captured.out assert "KILLED" in captured.out snapshot = tmp_path / ".metrics" / "mutate" / "demo.edn" assert snapshot.is_file() text = snapshot.read_text(encoding="utf-8") assert ":namespace \"demo\"" in text assert ":id \"defn/add\"" in text assert path.read_text(encoding="utf-8").startswith("def add")