Monkey patching dynamically redefines a program item at runtime. In tests, it can replace a deep dependency or real I/O resource with a controlled alternative, such as swapping a Rust-backed function for its Python implementation. section 7.2.1
A focused comparison test follows these steps:
- Keep the production function unchanged while retaining the original Python implementation as a test baseline. section 7.2.1
- Compute one result through the normal Rust-backed path. section 7.2.1
- Use pytest.MonkeyPatch.context to temporarily replace main.rust_json.sum with python_sum. section 7.2.1
- Compare both results, then expand the test with randomized inputs to expose behavioral differences. section 7.2.1
Comparing Python and Rust implementations
A helper first evaluates main.sum(input). Inside a MonkeyPatch.context block, it sets main.rust_json.sum to python_sum, evaluates main.sum(input) again, and asserts that the two results match. Introducing an extra +10 in the Rust function makes the assertion fail with visibly different values; rebuilding and correcting the code restores passing tests. section 7.2.1
Listing 7.17 Test comparing the output of Rust and Python versions
from pytest import MonkeyPatch
def test_compare_py_rust():
compare_py_and_rust(
['{ "name": "Stokes Baker", "value": 954832 }']
)
def python_sum(line):
import json
value = json.loads(line)
return value['value'] + len(value['name'])
def compare_py_and_rust(input):
rust_result = main.sum(input)
with MonkeyPatch.context() as m:
m.setattr(main.rust_json, 'sum', python_sum)
py_result = main.sum(input)
assert rust_result == py_result
The complete comparison test shows the scoped replacement, baseline function, assertion, and known input in one listing. section 7.2.1
