High-fidelity command mocking framework
Project description
Command Mock Framework
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 logreturns, but you get it wrong. - Real commands are slow: Running
docker psin 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.
- Record real command outputs to TOML files.
- Replay them instantly in tests.
- 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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
07262df742316cc44ee88f63d81bc73b202353a541480dd09335598ec7403a19
|
|
| MD5 |
aa173324450d7180ffd5bf370d9af5b1
|
|
| BLAKE2b-256 |
9b87df224e50231a051d0e55bac06d7a60b7b59bdbd2f00c1eb7182541faa2d8
|
Provenance
The following attestation bundles were made for orgecc_command_mock-0.1.3.tar.gz:
Publisher:
release.yml on elifarley/command-mock
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
orgecc_command_mock-0.1.3.tar.gz -
Subject digest:
07262df742316cc44ee88f63d81bc73b202353a541480dd09335598ec7403a19 - Sigstore transparency entry: 728014553
- Sigstore integration time:
-
Permalink:
elifarley/command-mock@5ac9089973d51d0ff5cd42d0096213231b5c9db1 -
Branch / Tag:
refs/tags/0.1.3 - Owner: https://github.com/elifarley
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5ac9089973d51d0ff5cd42d0096213231b5c9db1 -
Trigger Event:
push
-
Statement type:
File details
Details for the file orgecc_command_mock-0.1.3-py3-none-any.whl.
File metadata
- Download URL: orgecc_command_mock-0.1.3-py3-none-any.whl
- Upload date:
- Size: 11.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
73c51293823e74e97b2e8debe249a50d7db8b4312a4a94c324b8d8cf559b327c
|
|
| MD5 |
15ddeb199268b184683bbf5bbccc1a38
|
|
| BLAKE2b-256 |
c34bc38c19444a7f7ef63b19ac98a77ad55ca2883580099d407d81d2fbf653ef
|
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
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
orgecc_command_mock-0.1.3-py3-none-any.whl -
Subject digest:
73c51293823e74e97b2e8debe249a50d7db8b4312a4a94c324b8d8cf559b327c - Sigstore transparency entry: 728014562
- Sigstore integration time:
-
Permalink:
elifarley/command-mock@5ac9089973d51d0ff5cd42d0096213231b5c9db1 -
Branch / Tag:
refs/tags/0.1.3 - Owner: https://github.com/elifarley
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5ac9089973d51d0ff5cd42d0096213231b5c9db1 -
Trigger Event:
push
-
Statement type: