Muex.Sandbox (Muex v0.7.0)

View Source

Creates isolated working directories for parallel mutation testing.

Each sandbox mirrors the project structure using symlinks, with its own _build directory and a copy of the single mutated source file. This allows multiple mix test processes to run simultaneously without seeing each other's mutations.

Supports both standard Mix projects and umbrella projects. For umbrellas, the apps/ directory is mirrored (not lib/), and only the specific app being mutated has its _build artifacts deep-copied.

Structure (umbrella)

sandbox/
 mix.exs           symlink to project
 mix.lock          symlink to project
 config/           symlink to project
 deps/             symlink to project
 apps/             mirrored directory of symlinks
    my_app/lib/   directory of symlinks, except:
        mutated.ex  real file with mutated source
 _build/           symlinks + deep copy of mutated app

Summary

Functions

Applies a mutation to a sandbox by writing the mutated source to the sandbox's copy of the file, and deleting the stale beam so the child mix test process recompiles it.

Cleans up all sandbox directories.

Creates a pool of reusable sandbox directories.

Creates a single sandbox directory mirroring the project.

Restores a sandbox after a mutation by copying the original source file back over the mutated copy.

Types

sandbox()

@type sandbox() :: %{root: Path.t(), project_root: Path.t(), build_env: String.t()}

Functions

apply_mutation(sandbox, original_path, mutated_source, module_name)

@spec apply_mutation(sandbox(), Path.t(), String.t(), atom() | nil) ::
  {:ok, boolean()} | {:error, term()}

Applies a mutation to a sandbox by writing the mutated source to the sandbox's copy of the file, and deleting the stale beam so the child mix test process recompiles it.

Returns {:ok, false} on success (the child always recompiles), or {:error, reason}.

cleanup(sandboxes)

@spec cleanup([sandbox()]) :: :ok

Cleans up all sandbox directories.

create_pool(count, opts \\ [])

@spec create_pool(
  non_neg_integer(),
  keyword()
) :: [sandbox()]

Creates a pool of reusable sandbox directories.

Returns a list of sandbox structs that can be checked out by workers.

create_sandbox(root, project_root, build_env, test_paths)

@spec create_sandbox(Path.t(), Path.t(), String.t(), [String.t()]) :: sandbox()

Creates a single sandbox directory mirroring the project.

restore(sandbox, original_path)

@spec restore(sandbox(), Path.t()) :: :ok

Restores a sandbox after a mutation by copying the original source file back over the mutated copy.