Plan
- The page shows a one-screen read of sample-service: what each module owns, both endpoints, the real test run, and the three biggest risks with a fix.
- The data is real: pulled from reading
app/main.pyandtests/test_orders.py, and from an actualpytestrun in a sandbox — nothing here is invented. - The one interaction: the switch below flips the whole page between "before fix" and "after fix" — test counts, the failing test, and the diff all move together.
Modules
| Module | Owns |
|---|---|
| app/main.py | The FastAPI app, the in-memory ORDERS store (3 orders across 2 accounts), the order_total() pricing function, and both HTTP endpoints. |
| app/__init__.py | Empty — marks app as a package so tests can import app.main. |
| tests/test_orders.py | 5 tests against a FastAPI TestClient: order lookup (found/missing), pricing math on a 2-line order, an empty-order edge case, and account-level aggregation. |
Endpoints
| Endpoint | Input | Output | Notes |
|---|---|---|---|
| GET /orders/{order_id} | order_id: str (path) e.g. "A-1001" |
200: order object + total404: {"detail":"order not found"} |
Looks up a fixed in-memory dict; no query params, no body. |
| GET /accounts/{account}/total | account: str (path) e.g. "Account A" (URL-encode the space) |
200: {account, orders, total}404: {"detail":"account not found"} |
Exact, case-sensitive string match against every order's account field. |
Test summary
4Passed
1Failed
- test_get_order_ok PASS
- test_get_order_missing PASS
- test_total_two_lines FAIL
- test_empty_order_total_is_zero PASS
- test_account_total PASS
Top 3 risks
1
Order totals are wrong for any line with quantity > 1
app/main.py:17
order_total() summed qty + unit instead of qty * unit. Every total returned by both endpoints understated the real value — silently, with no error. Caught by test_total_two_lines, which asserted the correct product and failed against the addition.
This is the deliberate bug — click to toggle the fix
2
Malformed line data crashes with a raw 500, not a 4xx
app/main.py:16-17
order_total() assumes every line has numeric qty and unit keys, with no validation. Verified by hand: a line missing unit raises KeyError: 'unit'; a non-numeric qty raises TypeError. Today the store is fixed, so this can't fire — but the moment order data comes from a request body or a database, one bad record takes the endpoint down instead of returning a clean 4xx.
3
No bounds checking, and account lookup is case-sensitive with no normalization
app/main.py:17, 31
Negative quantities are accepted and silently produce a negative total (verified:
qty=-5, unit=100 → total=-500). Separately, /accounts/{account}/total does an exact string match with no case-folding or trimming, so "account a" 404s even though "Account A" exists — a correctness trap for any caller that doesn't copy the casing exactly.
Proposed fix — risk #1
--- a/app/main.py +++ b/app/main.py @@ -13,6 +13,6 @@ def order_total(order: dict) -> float: """Sum of qty * unit across lines. Empty orders total 0.""" total = 0.0 for line in order["lines"]: - total += line["qty"] + line["unit"] + total += line["qty"] * line["unit"] return round(total, 2)
Checked by hand
One thing to check yourself: order A-1002 has 10 × GIS/MA-PRO at $45 plus 1 × GIS-STD at $1200. Correct total is 10×45 + 1×1200 = 1,650.00. Before the fix the API returned 1,256.00 (10+45 + 1+1200); after the fix it returns 1,650.00. Flip the switch above and confirm those two numbers yourself against
data/sample-service/app/main.py before trusting this page.