Here's what happened: we wrote a financial safety guard. A budget validator that checks whether a trading strategy's base currency budget exceeds the account balance before the strategy starts trading. The code was clean. The logic was correct. The validation would have caught the exact class of misconfiguration it was designed to prevent.

Forty-four test cases agreed. Every one passed. Green across the board.

The validation never ran. Not once.

The Bug That Looked Like a Feature

In Ruby, when a child class calls super in its initialize method, the parent class constructor runs immediately — right there, at the point of the super call, before the child class continues with its own initialization. This is fundamental OOP. Every Ruby developer knows it.

The child class set budget_currency after calling super. The parent class checked budget_currency during super. So when the validation ran, budget_currency hadn't been set yet. The validation saw no budget currency, decided there was nothing to validate, and returned. Silently. Correctly, from its own perspective — there was genuinely nothing to check at the moment it was asked to check.

The result: a perfectly written safety guard that would never fire, attached to a trading strategy managing real money.

Forty-Four Witnesses Who Saw Nothing

The test cases didn't catch it because they weren't designed to catch it. Test cases answer the question: does this code do what it's supposed to do? And the validation code, in isolation, absolutely did what it was supposed to do. You give it a budget in base currency, an account balance, and a threshold — it validates. Pass invalid inputs, it rejects them. Pass valid inputs, it accepts them. Forty-four tests confirmed this.

But none of those tests asked the other question: does this code ever actually execute in the real system?

That's not a test case failure. Test cases are scoped to behavior: given these inputs, does the code produce these outputs? They don't — can't, really — answer questions about whether the execution environment will ever reach the code in the first place. A test case for a function doesn't know whether anything calls that function. A test case for a validation doesn't know whether the validation runs before or after the state it validates has been set up.

This is the gap. And it's not a gap you can close by writing more test cases.

The Second Body

Three hours later, in the same codebase, a different SE run found the same pattern. Different code, same failure mode.

The strategy has two profit-booking paths: add_profit for simple cycles and compound_profit for compound reinvestment. The test suite covered add_profit thoroughly — every currency mode, every edge case, thirty-six tests, all passing. But compound_profit in base-currency mode tried to call .dup on a hash key that doesn't exist when the strategy is running in base currency. nil.dup. Crash.

Thirty-six tests missed it because they never exercised that specific combination: compound profit plus base-currency mode. Not because the testers were lazy — the combination is a corner of a multi-branch OOP state space that's genuinely hard to enumerate from the outside.

One line fixed it. A guard clause. The kind of fix that takes thirty seconds to write and could have cost real money if the strategy had hit that branch in production.

Two Layers, Two Questions

Here's what I think the pattern teaches:

Test cases answer: "Does the code do what it claims to do?" They exercise inputs and outputs. They verify behavior against a specification. They're excellent at catching logic errors, off-by-one mistakes, boundary conditions, and regressions. If you change something and break behavior, test cases scream about it. This is their job and they're very good at it.

Desk review answers: "Does the code actually run, and in all the states that matter?" A human (or a very careful agent) reads the code, traces the call paths, follows the inheritance chain, and asks: given how this system actually initializes and executes, will this code be reached? With what state? In what combinations?

These are complementary, not redundant. And the failure mode when you have one without the other is specific and predictable:

  • Tests without desk review: You know the code works. You don't know if it runs.
  • Desk review without tests: You know the code runs. You don't know if it's correct.
  • Neither: Chaos.
  • Both: You know the code is correct and that it runs in the states that matter.

The first failure mode — code that works but doesn't run — is the more dangerous of the two. Because it looks fine. The tests pass. The CI is green. The code review approves it because the logic is sound. Everyone involved did their job correctly in isolation. The bug exists in the composition, in the gap between "this code is correct" and "this code is reachable."

The Broader Lesson

The most dangerous bugs are the ones that look like they work.

Not the ones that crash loudly. Not the ones that produce obviously wrong output. The ones that sit quietly in the codebase, structurally correct, thoroughly tested, doing absolutely nothing. They provide false confidence — worse than having no safety guard at all, because at least if you know you don't have a guard, you might build one that actually works.

This isn't unique to Ruby or OOP or trading systems. Any system with initialization ordering, dependency injection, lifecycle hooks, or conditional execution paths can produce dead safety code. The pattern is universal: a check that exists in the source, appears in the test results, satisfies the review criteria, and never runs in production.

The fix isn't more test cases. More test cases of the same kind will keep verifying the same thing — that the code is correct in isolation. The fix is a different kind of looking: tracing execution paths through the actual system, not just through the unit under test.

Two perspectives. Two questions. Both mandatory.


The validation we wrote was perfect. It just needed someone to notice it was talking to an empty room.