mirror of
https://github.com/unclebob/mutator.git
synced 2026-11-06 18:23:50 +00:00
A package path is one argument. Git status uses NUL records and returns git's status. A failed coverage command leaves reports unread, coverage keeps the longest path match, and site walks no longer recurse.
156 lines
5.8 KiB
Python
156 lines
5.8 KiB
Python
import sys
|
|
|
|
from mutator.runner import CommandRunner, _clojure_command, _python_command, nearest
|
|
from mutator.runner import test_plan as plan_command
|
|
|
|
|
|
def test_nearest_walks_up_to_the_marker(tmp_path):
|
|
root = tmp_path / "proj"
|
|
nested = root / "src" / "demo"
|
|
nested.mkdir(parents=True)
|
|
(root / "pyproject.toml").write_text("", encoding="utf-8")
|
|
source = nested / "app.py"
|
|
source.write_text("x = 1\n", encoding="utf-8")
|
|
assert nearest(source, "pyproject.toml", root) == root
|
|
assert nearest(nested, "pyproject.toml", root) == root
|
|
assert nearest(source, "missing.toml", root) is None
|
|
|
|
|
|
def test_clojure_commands(tmp_path):
|
|
bb = tmp_path / "bb-spec"
|
|
bb.mkdir()
|
|
(bb / "bb.edn").write_text('{:tasks {spec "spec"}}', encoding="utf-8")
|
|
assert _clojure_command(bb) == ["bb", "spec", "--tag", "~no-mutate"]
|
|
|
|
bb_test = tmp_path / "bb-test"
|
|
bb_test.mkdir()
|
|
(bb_test / "bb.edn").write_text("{:tasks {test (clojure \"-M:test\")}}", encoding="utf-8")
|
|
assert _clojure_command(bb_test) == ["bb", "test"]
|
|
|
|
spec = tmp_path / "spec"
|
|
spec.mkdir()
|
|
(spec / "deps.edn").write_text(
|
|
"{:aliases {:spec {:extra-deps {speclj/speclj {}}}}}", encoding="utf-8"
|
|
)
|
|
assert _clojure_command(spec) == ["clj", "-M:spec", "--tag", "~no-mutate"]
|
|
|
|
spec_only = tmp_path / "spec-only"
|
|
spec_only.mkdir()
|
|
(spec_only / "deps.edn").write_text("{:aliases {:spec {}}}", encoding="utf-8")
|
|
assert _clojure_command(spec_only) == ["clj", "-M:spec"]
|
|
|
|
plain = tmp_path / "plain"
|
|
plain.mkdir()
|
|
(plain / "deps.edn").write_text("{:deps {}}", encoding="utf-8")
|
|
assert _clojure_command(plain) == ["clj", "-M:test"]
|
|
|
|
|
|
def _executable(path):
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
path.write_text("#!/bin/sh\n", encoding="utf-8")
|
|
path.chmod(0o755)
|
|
|
|
|
|
def test_python_command_uses_an_absolute_project_interpreter(tmp_path):
|
|
project = tmp_path / "proj"
|
|
dot = project / ".venv" / "bin" / "python"
|
|
_executable(dot)
|
|
(project / "pytest.ini").write_text("[pytest]\n", encoding="utf-8")
|
|
assert _python_command(project) == [str(dot.absolute()), "-m", "pytest"]
|
|
|
|
other = tmp_path / "other"
|
|
plain = other / "venv" / "bin" / "python"
|
|
_executable(plain)
|
|
assert _python_command(other) == [str(plain.absolute()), "-m", "unittest", "discover"]
|
|
|
|
_executable(other / ".venv" / "bin" / "python")
|
|
assert _python_command(other) == [
|
|
str((other / ".venv" / "bin" / "python").absolute()),
|
|
"-m",
|
|
"unittest",
|
|
"discover",
|
|
]
|
|
|
|
|
|
def test_python_command_keeps_the_virtualenv_symlink(tmp_path):
|
|
project = tmp_path / "proj"
|
|
target = project / "real-python"
|
|
_executable(target)
|
|
link = project / ".venv" / "bin" / "python"
|
|
link.parent.mkdir(parents=True)
|
|
link.symlink_to(target)
|
|
(project / "pytest.ini").write_text("[pytest]\n", encoding="utf-8")
|
|
assert _python_command(project) == [str(link.absolute()), "-m", "pytest"]
|
|
|
|
|
|
def test_python_command_falls_back_when_the_virtualenv_cannot_run(tmp_path):
|
|
project = tmp_path / "proj"
|
|
binary = project / ".venv" / "bin" / "python"
|
|
binary.parent.mkdir(parents=True)
|
|
binary.write_text("", encoding="utf-8")
|
|
assert _python_command(project) == [sys.executable, "-m", "unittest", "discover"]
|
|
|
|
missing = tmp_path / "missing"
|
|
missing.mkdir()
|
|
assert _python_command(missing) == [sys.executable, "-m", "unittest", "discover"]
|
|
|
|
|
|
def test_python_commands(tmp_path):
|
|
pytest_dir = tmp_path / "py"
|
|
pytest_dir.mkdir()
|
|
(pytest_dir / "pytest.ini").write_text("[pytest]\n", encoding="utf-8")
|
|
assert _python_command(pytest_dir)[-2:] == ["-m", "pytest"]
|
|
|
|
unit = tmp_path / "unit"
|
|
unit.mkdir()
|
|
assert _python_command(unit)[-3:] == ["-m", "unittest", "discover"]
|
|
|
|
cfg = tmp_path / "cfg"
|
|
cfg.mkdir()
|
|
(cfg / "setup.cfg").write_text("[tool:pytest]\n", encoding="utf-8")
|
|
assert _python_command(cfg)[-2:] == ["-m", "pytest"]
|
|
|
|
project = tmp_path / "proj"
|
|
project.mkdir()
|
|
(project / "pyproject.toml").write_text("[project]\ndependencies=['pytest']\n", encoding="utf-8")
|
|
assert _python_command(project)[-2:] == ["-m", "pytest"]
|
|
|
|
conf = tmp_path / "conf"
|
|
conf.mkdir()
|
|
(conf / "conftest.py").write_text("", encoding="utf-8")
|
|
assert _python_command(conf)[-2:] == ["-m", "pytest"]
|
|
|
|
|
|
def test_a_go_package_path_is_one_argument(tmp_path):
|
|
root = tmp_path / "proj"
|
|
package = root / "a;echo no"
|
|
package.mkdir(parents=True)
|
|
(root / "go.mod").write_text("module example.com/demo\n", encoding="utf-8")
|
|
source = package / "widget.go"
|
|
source.write_text("package main\nfunc Run() int { return 1 }\n", encoding="utf-8")
|
|
command, directory = plan_command(root, source, "go", None)
|
|
assert command == ["go", "test", "-count=1", "./a;echo no"]
|
|
assert directory == root
|
|
echoed = CommandRunner().run(["/bin/echo", command[-1]], directory, None)
|
|
assert echoed.code == 0
|
|
assert echoed.output.strip() == "./a;echo no"
|
|
|
|
spaced = root / "my dir" / "widget.go"
|
|
spaced.parent.mkdir()
|
|
spaced.write_text("package main\nfunc Run() int { return 1 }\n", encoding="utf-8")
|
|
command, _directory = plan_command(root, spaced, "go", None)
|
|
assert command == ["go", "test", "-count=1", "./my dir"]
|
|
override, override_dir = plan_command(root, source, "go", "go test ./...")
|
|
assert override == "go test ./..."
|
|
assert override_dir == root.resolve()
|
|
|
|
|
|
def test_a_worker_overlay_is_imported_ahead_of_the_environment(tmp_path):
|
|
worker = tmp_path / "target" / "mutation-workers" / "run-1" / "worker-0"
|
|
(worker / "src").mkdir(parents=True)
|
|
(worker / "src" / "demo.py").write_text("VALUE = 'worker'\n", encoding="utf-8")
|
|
command = f"{sys.executable} -c 'import demo; print(demo.VALUE)'"
|
|
result = CommandRunner().run(command, worker, 5)
|
|
assert result.code == 0
|
|
assert result.output.strip() == "worker"
|