Skip to main content

High-fidelity command mocking framework

Project description

Command Mock Framework

PyPI version Tests

High-fidelity, deterministic command mocking for Python tests.

Stop mocking subprocess.run with invented strings. Record real command outputs once, store them in version control, and replay them during tests.


The Problem

Testing code that wraps CLI tools (Git, Docker, Kubectl, npm) is painful.

  • Manual mocks are brittle: You guess what git log returns, but you get it wrong.
  • Real commands are slow: Running docker ps in every test kills performance.
  • Integration tests are flaky: Environments change, causing non-deterministic failures.

The Solution

Command Mock Framework sits between your code and subprocess.

  1. Record real command outputs to TOML files.
  2. Replay them instantly in tests.
  3. Match commands flexibly using template placeholders.

Quick Example

1. Record the real behavior:

from command_mock.recorder import CommandMockRecorder

# Run this once to generate 'mocks/git/log/follow.toml'
recorder = CommandMockRecorder("git")
recorder.record_scenario(
    command=["git", "log", "--follow", "--", "{filepath}"],
    scenario_name="basic_history",
    template_vars={"filepath": "app.py"}
)

2. Use it in your test:

def test_get_history(command_mock):
    # Load the mock (command_mock is a pytest fixture)
    mock_fn = command_mock.get_subprocess_mock("log/follow.toml", "basic_history")

    # Patch subprocess.run
    with patch('subprocess.run', side_effect=mock_fn):
        # This executes FAST and returns REAL git output
        # It matches 'git log ... -- app.py' OR 'git log ... -- other.py'
        history = my_git_wrapper.get_history("app.py")

    assert len(history) == 5

Installation

pip install orgecc-command-mock

Usage Guide

1. Setup

Add the pytest plugin to your conftest.py:

# tests/conftest.py
import pytest
from pathlib import Path
from command_mock.recorder import CommandMockRecorder
from command_mock.player import CommandMockPlayer

@pytest.fixture
def command_mock(request):
    """Fixture that switches between Player (default) and Recorder."""
    # Point this to where you want to store your TOML files
    fixtures_root = Path(__file__).parent

    if request.config.getoption("--regenerate-mocks"):
        return CommandMockRecorder("git", fixtures_root=fixtures_root)
    else:
        return CommandMockPlayer("git", fixtures_root=fixtures_root)

def pytest_addoption(parser):
    parser.addoption("--regenerate-mocks", action="store_true", help="Record new mocks")

2. Recording Mocks

Create a script (e.g., tests/generate_mocks.py) to generate your test data. This ensures your mocks are reproducible.

from command_mock.recorder import CommandMockRecorder

def generate():
    recorder = CommandMockRecorder("git")

    # You can even use setup scripts to create real repo states!
    repo = recorder.create_test_repo("scripts/setup_repo.sh")

    recorder.record_scenario(
        command=["git", "status"],
        scenario_name="clean_state",
        output_path="status/clean.toml",
        repo_path=repo
    )

if __name__ == "__main__":
    generate()

3. Flexible Matching

This is the framework's superpower. You don't need a mock for every single argument variation. Use placeholders in your templates.

Embedded Placeholders:

# Template in TOML:
command = ["git", "log", "--grep={term}"]

# Matches all of these in tests:
["git", "log", "--grep=fix"]
["git", "log", "--grep=feat"]

Standalone Placeholders:

# Template in TOML:
command = ["git", "add", "{filepath}"]

# Matches all of these in tests:
["git", "add", "src/main.py"]
["git", "add", "tests/test_core.py"]

Dynamic Flag Stripping: The player automatically handles flags that change every run (like --since="1 hour ago"), matching the core command while ignoring the dynamic parts.

Development

This project uses a Makefile for all development tasks.

make install      # Install dev dependencies
make test         # Run tests
make format       # Format code (Black/Ruff)
make ci           # Run full CI suite locally

For detailed contribution guidelines, see CLAUDE.md.

License

Apache 2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

orgecc_command_mock-0.1.3.tar.gz (27.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

orgecc_command_mock-0.1.3-py3-none-any.whl (11.8 kB view details)

Uploaded Python 3

File details

Details for the file orgecc_command_mock-0.1.3.tar.gz.

File metadata

  • Download URL: orgecc_command_mock-0.1.3.tar.gz
  • Upload date:
  • Size: 27.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for orgecc_command_mock-0.1.3.tar.gz
Algorithm Hash digest
SHA256 07262df742316cc44ee88f63d81bc73b202353a541480dd09335598ec7403a19
MD5 aa173324450d7180ffd5bf370d9af5b1
BLAKE2b-256 9b87df224e50231a051d0e55bac06d7a60b7b59bdbd2f00c1eb7182541faa2d8

See more details on using hashes here.

Provenance

The following attestation bundles were made for orgecc_command_mock-0.1.3.tar.gz:

Publisher: release.yml on elifarley/command-mock

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file orgecc_command_mock-0.1.3-py3-none-any.whl.

File metadata

File hashes

Hashes for orgecc_command_mock-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 73c51293823e74e97b2e8debe249a50d7db8b4312a4a94c324b8d8cf559b327c
MD5 15ddeb199268b184683bbf5bbccc1a38
BLAKE2b-256 c34bc38c19444a7f7ef63b19ac98a77ad55ca2883580099d407d81d2fbf653ef

See more details on using hashes here.

Provenance

The following attestation bundles were made for orgecc_command_mock-0.1.3-py3-none-any.whl:

Publisher: release.yml on elifarley/command-mock

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page