PärPod by Claude Code
PärPod by Claude Code
PärPod by Claude Code
Sidequest: Monkeypatching, or How the Tests Lie to the Ledger on Purpose
6m · Oct 14, 2026
Sidequest: Monkeypatching, or How the Tests Lie to the Ledger on Purpose

Sidequest: Monkeypatching, or How the Tests Lie to the Ledger on Purpose

Cold open

Monkeypatching means swapping out a piece of a running program for a stand-in while a test runs, then putting the original back the moment the test is over.

That is it. The rest of this episode is about why your ledger tests do this dozens of times, and why it is the main thing standing between a test run and a real voucher in Bokio.

Where it showed up

You were watching the session put a "Bokför" button on the Froda card. Codex had blocked the first version over three real holes: overlapping reports could book the same payment twice, a dropped connection lost track of what had already gone through, and the record file could get corrupted if a write was interrupted. The session fixed all three, wrote new tests, and 157 of them passed. Scroll past those tests and the same line shows up over and over: monkeypatch, set attribute. Swap this, swap that.

The tricky part is that this code posts real vouchers to Bokio, for Årebladet AB, with real money behind them. You cannot test a "book it" button by pressing it against the real Bokio 157 times. Your accountant would notice, and so would the 5000-request monthly quota.

The mental model

Think of a Python program as a building where every function hangs on a labelled hook. Somewhere in the ledger there is a hook labelled "post to Bokio", and the booking code does not hold the function itself. It walks over to that hook every time and takes whatever is hanging there.

Monkeypatching walks in before the booking code does and hangs something else on that hook. In the Froda booking tests, "post to Bokio" gets replaced with a fake that just hands back made-up voucher numbers starting at V1400, and also writes down every call it receives. "Fetch journal entries from Bokio" gets replaced with a fake that answers "the ledger is empty". "Read this Froda PDF" gets replaced with a fake that returns 3 fixed payment rows, so no PDF ever has to be parsed. Then the test starts the real ledger web server, sends it real form posts, and checks what happened.

The important detail is that the booking code has no idea. It runs exactly the same logic it would run on your Mac on a Monday morning. The only difference is what sits on the hooks. So the test checks the real decision-making (fingerprint matches, the review box is ticked, refuse overlapping reports) with nothing real at the ends.

The second half of the word matters just as much: the putting back. The pytest test tool hands every test a little helper called monkeypatch, and that helper keeps a list of every swap. When the test finishes, whether it passed, failed or blew up, the helper puts every original back on its hook. Without that, one test's fake Bokio would leak into the next test, and you would get the classic bug where tests pass one at a time and fail together, or worse, the other way round.

Why "monkey"? The legend is that it started as "guerrilla patch", because you are changing code at runtime with no permission from its author, and somewhere along the way guerrilla turned into gorilla and then monkey. Programmers name things like a tired child naming a goldfish.

The part that actually protects your money

There is one file in the ledger tests that every test runs through automatically, before anything else. It does three swaps. It replaces the raw network call to Bokio with a function that fails the test on the spot with "network call in test". It replaces the pause between retries with something that only notes how long it would have waited, so tests do not sit around. And it replaces the Keychain token lookup with a dummy string.

So the safety net is not "please remember to mock Bokio". It is "the wire to Bokio has been cut for every test, and touching it is a failure". If a future change accidentally reaches the real API in a test, the suite goes red instead of quietly booking something.

There is also a nice trick in the status tests. One of Codex's holes was the record file getting corrupted mid-write. The fix writes to a temporary file and then swaps it into place in one atomic step. To prove that, a test monkeypatches the operating system's "replace this file" call with a spy that checks the temporary file sits next to the real one, and that the real file has not been touched yet, and only then does the real replace. You cannot easily catch a write in the middle any other way, so the test puts a witness on that hook.

The catch

Monkeypatching is a lie you tell on purpose, and a lie can drift away from the truth. The fake Bokio says what the session believed Bokio says. If Bokio's real responses change shape, every test stays green and the first live press fails. That is why the session said the button has only run against a mocked Bokio, and that its real first test is the October Froda report. 157 passing tests show the logic is right. They do not show Bokio agrees.

It is also why your rules ask for mutation testing: the session removed the live check and confirmed the test then failed. A fake that cannot make a test fail is just decoration.

Elsewhere in the estate

Same idea throughout the ledger: the Qred fetch tests swap out the Google Workspace helper and the subprocess call so no mail is actually fetched, and the Bokio client tests swap the raw web call for canned answers to check retries and paging. Any repo of yours with a pytest suite and an outside service almost certainly does the same.

Close

If you remember one thing: monkeypatching hangs a fake on the hook the real code reaches for, only for one test, so the ledger's real logic runs against a pretend Bokio, and the network is cut so a test can never book real money.