I build a desktop options trading tool with Claude Code. Everything runs in a sandbox account. On Nov 13 it threw this:
AttributeError: 'Front' object has no attribute '_say'
How it hid for 18 days
The trading window is handed a small Front object that stands in for the engine. On Oct 26, a change had the window call self.engine._say(...) in two places:
- in the constructor, when the configured screen can't be found
- in a check that runs every 1.5 seconds and moves the window back if it drifts off its screen
Front never got a _say.
Two tests covered the change. Both opened ui.py and checked that the call was in the file. It was, so both passed on every run for 18 days.
On Nov 13 the window was moved off its screen, the check fired, and the call crashed. The constructor path would have been worse: with that monitor unplugged, the window would not have opened at all.
Why the tests missed it
A test that searches source text proves the text is there. It never runs the line. Python only looks up self.engine._say when that line executes, and in this window it executes in two rare situations.
The test, written first
Before touching the fix, the new test went in, and it had to fail on the old code. Its first check walks ui.py's syntax tree, collects every attribute the window reads from self.engine, and asserts each one exists on Front. Here's a minimal version of the idea:
import ast def attrs_read_from_engine(path): tree = ast.parse(open(path, encoding="utf-8").read()) names = set() for node in ast.walk(tree): if (isinstance(node, ast.Attribute) and isinstance(node.value, ast.Attribute) and node.value.attr == "engine" and isinstance(node.value.value, ast.Name) and node.value.value.id == "self"): names.add(node.attr) return names def test_front_has_everything_the_window_uses(): from ticket import Front missing = sorted(n for n in attrs_read_from_engine("ui.py") if not hasattr(Front, n)) assert not missing, f"Front is missing: {missing}" If your stand-in sets attributes in __init__, check an instance instead of the class.
The second check makes sure _say hands the message only to the page that's on screen.
Old code: 0 passed, 2 failed. Then the fix, six lines on Front. New code: 4 passed.
The first check covers the whole type. The next time anyone, human or AI, adds a call the stand-in doesn't support, the suite fails the same day.
The check you can copy
Search your suite for tests that read source files as text. Each one only proves some code exists. Swap it for a test that builds the real object and calls it, or one that checks the real type has everything its caller uses.
Follow the loop
This bug is now in my AI's mistake log under "a test that skips the real path." Each round of the loop goes up on YouTube first, with which piles grew.
Subscribe to Dr_Delta on YouTube
Have you found tests like this in your own suite? Tell me in the comments.

