oct
Loading...
Searching...
No Matches
oct.mutation.runner Namespace Reference

Classes

class  MutantOutcome
class  RunReport

Functions

list[str] _pytest_argv (Path tests)
tuple[int|None, float] _run_tests (Path tests, Path cwd, int timeout, Path pycache_dir)
float _verify_baseline (Path tests, Path cwd, int timeout, Path pycache_dir)
RunReport run_mutants (*, str|Path target, str|Path tests, int timeout=DEFAULT_TIMEOUT_SECONDS, str|Path|None root=None, Sequence[str]|None mutant_ids=None, Callable[[str], None]|None on_progress=None)
list[Mutant] _select (list[Mutant] mutants, Sequence[str]|None mutant_ids)
list[MutantOutcome] _run_each (Iterable[Mutant] mutants, Path target, Path tests, Path repo_root, str relpath, int timeout, Path cache_dir, Callable[[str], None] report_progress)
str _classify (int|None returncode)

Variables

str STATUS_KILLED = "killed"
str STATUS_SURVIVED = "survived"
str STATUS_TIMEOUT = "timeout"
int _PYTEST_NO_TESTS_COLLECTED = 5
int DEFAULT_TIMEOUT_SECONDS = 60

Detailed Description

Purpose
-------
Run a test command once per mutant and classify each outcome honestly.

Responsibilities
----------------
- Prove the tests are green on the pristine target before judging any mutant.
- Execute the given test path in a subprocess with a per-mutant timeout.
- Classify each mutant as killed, survived, or timeout, never conflating them.
- Stream per-mutant progress so a long run is never silent.

Diagnostics
-----------
Domain: OCT-MUTATION
Levels:
    L2 - lifecycle
    L3 - per-mutant execution details
    L4 - deep tracing

Contracts
---------
- A timeout is its own class and is never counted as a kill.
- The pristine baseline must pass; without it every mutant would look killed,
  so a red or empty baseline is a named refusal rather than a 100% kill rate.
- Each subprocess gets a fresh bytecode-cache directory, so no run can be
  decided by a stale ``.pyc`` from the previous mutant.
- Runtime is mutant count times one test run; the caller is told the count
  before the loop starts.

Dependencies
------------
- oct.mutation.engine (enumeration and mutant identity)
- oct.mutation.sandbox (target refusal, apply, and restore)
- subprocess (per-mutant pytest execution)

Function Documentation

◆ _classify()

str oct.mutation.runner._classify ( int | None returncode)
protected
Map one test run's exit code onto the three pinned outcome classes.

Definition at line 353 of file runner.py.

Here is the caller graph for this function:

◆ _pytest_argv()

list[str] oct.mutation.runner._pytest_argv ( Path tests)
protected
Return the pytest command used for both the baseline and each mutant.

``-x`` stops at the first failure because one failure already proves the
mutant was noticed. Plugin autoloading for randomisation and the cache is
switched off so a run is decided by the mutant and nothing else.

Definition at line 164 of file runner.py.

Here is the caller graph for this function:

◆ _run_each()

list[MutantOutcome] oct.mutation.runner._run_each ( Iterable[Mutant] mutants,
Path target,
Path tests,
Path repo_root,
str relpath,
int timeout,
Path cache_dir,
Callable[[str], None] report_progress )
protected
Apply, run, and classify each mutant, restoring the target every time.

Definition at line 319 of file runner.py.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _run_tests()

tuple[int | None, float] oct.mutation.runner._run_tests ( Path tests,
Path cwd,
int timeout,
Path pycache_dir )
protected
Run the tests once, returning the exit code and elapsed seconds.

The exit code is ``None`` when the run exceeded ``timeout``; the child is
killed by :func:`subprocess.run` at that point. Grandchildren the test run
spawned are not tracked, which is a named residual rather than a guarantee.

Definition at line 185 of file runner.py.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _select()

list[Mutant] oct.mutation.runner._select ( list[Mutant] mutants,
Sequence[str] | None mutant_ids )
protected
Return the requested subset, refusing an id the target does not hold.

Definition at line 304 of file runner.py.

Here is the caller graph for this function:

◆ _verify_baseline()

float oct.mutation.runner._verify_baseline ( Path tests,
Path cwd,
int timeout,
Path pycache_dir )
protected
Refuse unless the pristine target passes the given tests.

Skipping this check is how a mutation tool reports a flattering kill rate
it did not earn: against a red suite every mutant "fails the tests" and is
scored as killed.

Definition at line 217 of file runner.py.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ run_mutants()

RunReport oct.mutation.runner.run_mutants ( * ,
str | Path target,
str | Path tests,
int timeout = DEFAULT_TIMEOUT_SECONDS,
str | Path | None root = None,
Sequence[str] | None mutant_ids = None,
Callable[[str], None] | None on_progress = None )
Run every enumerated mutant of ``target`` and classify each outcome.

``mutant_ids`` narrows the run to named mutants; it exists for tests and
is deliberately not a CLI flag in v1.

Definition at line 250 of file runner.py.

Here is the call graph for this function:

Variable Documentation

◆ _PYTEST_NO_TESTS_COLLECTED

int oct.mutation.runner._PYTEST_NO_TESTS_COLLECTED = 5
protected

Definition at line 72 of file runner.py.

◆ DEFAULT_TIMEOUT_SECONDS

int oct.mutation.runner.DEFAULT_TIMEOUT_SECONDS = 60

Definition at line 74 of file runner.py.

◆ STATUS_KILLED

str oct.mutation.runner.STATUS_KILLED = "killed"

Definition at line 65 of file runner.py.

◆ STATUS_SURVIVED

str oct.mutation.runner.STATUS_SURVIVED = "survived"

Definition at line 66 of file runner.py.

◆ STATUS_TIMEOUT

str oct.mutation.runner.STATUS_TIMEOUT = "timeout"

Definition at line 67 of file runner.py.