Quant Memo
Foundational

Unit Testing Fundamentals

A unit test checks one small piece of code in isolation against a known expected result, run automatically every time the code changes, so a broken calculation is caught in seconds rather than discovered live weeks later.

Prerequisites: Version Control with Git

Quant code is full of small, easy-to-get-subtly-wrong calculations: a P&L formula, a Sharpe ratio, a bond's accrued interest. Get one sign flipped or one day-count convention wrong and the code still runs without error — it just quietly produces a plausible, incorrect number, and nothing points at the bug until a live trade loses money for a reason nobody can explain. A unit test is a short piece of code that calls one function with known inputs and checks the output against a known correct answer, and a suite of these runs automatically on every change, so a broken calculation fails loudly in seconds instead of silently in production.

The idea: isolate one function, assert one known answer

A good unit test is small, fast, and deterministic: it tests one function's behavior, not the whole system, and it doesn't depend on a live database, network call, or the current date. The standard shape is arrange, act, assert — set up inputs, call the function, check the result.

def annualized_sharpe(returns, rf=0.0, periods_per_year=252):
    excess = [r - rf / periods_per_year for r in returns]
    mean = sum(excess) / len(excess)
    var = sum((r - mean) ** 2 for r in excess) / (len(excess) - 1)
    std = var ** 0.5
    return (mean / std) * (periods_per_year ** 0.5)

def test_sharpe_of_constant_returns_is_undefined():
    # zero volatility -> division by zero should raise, not silently return inf
    import pytest
    with pytest.raises(ZeroDivisionError):
        annualized_sharpe([0.01, 0.01, 0.01])

def test_sharpe_known_value():
    returns = [0.01, -0.005, 0.02, 0.0, -0.01]
    result = annualized_sharpe(returns)
    assert abs(result - 0.876) < 0.01   # precomputed by hand / reference implementation

Worked example: catching a real bug

Suppose annualized_sharpe had a bug — dividing by len(excess) instead of len(excess) - 1 for the variance (population instead of sample variance). Both versions run without error and return plausible-looking numbers. The test test_sharpe_known_value was written against a value computed independently by hand, so it fails: assert abs(result - 0.876) < 0.01 breaks because the buggy version returns something like 0.891. Running the test suite (pytest) after every code change surfaces this mismatch immediately, tied to the exact commit that introduced it — instead of surfacing as "the live Sharpe reporting looks slightly off" three weeks later with no obvious cause.

A unit test is only as good as the expected value it checks against. "The function ran without crashing" is not a test — the assertion needs an independently derived correct answer (by hand, from a textbook example, or from a trusted reference implementation), or a bug that changes the number without crashing the code will sail through untested.

Good unit tests also cover the boundaries a happy-path example skips: an empty input, a single data point, all-zero returns, a negative value where only positives were expected. Each of these tends to expose a different class of bug — division by zero, an off-by-one in a loop, an assumption baked into the math that doesn't hold at the edge. A function tested only against "normal" inputs can look completely correct while failing the moment real data does something unusual, which in market data happens more often than the happy path would suggest: a newly listed stock with one day of history, a corporate action that zeroes out a return, a halted session with no trades at all.

function typical input edge case error case
A test suite worth trusting checks the typical case, at least one edge case, and at least one input that should be rejected outright.

Where it shows up

Quant-dev interviews and take-homes frequently grade on whether you wrote tests at all, and whether they check meaningful cases: the typical value, an edge case (empty input, all-zero returns, a single data point), and an error case (invalid input that should raise rather than silently produce garbage). Writing a test for the function you were just asked to implement, unprompted, is a strong signal in a live coding interview.

In production, unit tests are the first and cheapest layer of a testing strategy: they run in seconds as part of CI on every commit (see Continuous Integration Pipelines), catching most regressions before a slower integration test or a human reviewer ever sees the change. Pricing libraries, risk calculations, and order-sizing logic are exactly the kind of code that gets the most unit test coverage, because a silent numerical bug there is expensive.

Write the test for the bug before fixing the bug. Confirm it fails against the broken code, then fix the code and confirm the test now passes — this proves the test actually catches the failure mode, rather than passing vacuously regardless of whether the bug exists.

Related concepts

Practice in interviews

Further reading

  • Beck, Test-Driven Development: By Example
ShareTwitterLinkedIn