Repo X-ray: sample-service
Architecture and health dashboard. Source: data/sample-service/, read and tested on 2026-09-07 by Gaurang Gehlot with Claude Code.
Modules and what each owns
| File | Owns | Lines |
|---|---|---|
| app/main.py | Everything runtime: the FastAPI app, the in-memory ORDERS store (3 orders, 2 accounts), order_total(), and both route handlers. | 34 |
| app/__init__.py | Empty package marker so from app.main import app resolves. | 0 |
| tests/test_orders.py | Five tests through TestClient and direct calls to order_total(). Imports the live ORDERS dict, so tests share state with the app. | 28 |
| pytest.ini | testpaths = tests, pythonpath = .. This is why the tests import app.main without packaging. | 3 |
| requirements.txt | fastapi, httpx, pytest. No pins. | 3 |
| README.md | Run instructions. Says "two endpoints" and "one test fails", both true. | 5 |
Endpoints, from the router not the README
Read from app.routes at import time. Both handlers are GET only. Responses are verbatim from the running app before the fix.
| Route | Input | 200 response | 404 |
|---|---|---|---|
| GET /orders/{order_id} main.py:21 |
Path param order_id, string, exact match against the dict key. |
{"id":"A-1001","account":"Account A","lines":[{"sku":"GIS-STD","qty":2,"unit":1200.0}],"total":1202.0} | {"detail":"order not found"} |
| GET /accounts/{account}/total main.py:29 |
Path param account, string, case-sensitive equality over a linear scan of all orders. Spaces must be URL-encoded. |
{"account":"Account A","orders":2,"total":2458.0} | {"detail":"account not found"} |
| GET /docs, /docs/oauth2-redirect, /redoc, /openapi.json | Added by FastAPI, not by this code. Not in the README. Worth knowing they are public if this ever ships. | ||
No POST, PUT, or DELETE. No response models, so the JSON shape above is what the dict happens to contain, not a contract.
Test summary
4 passed, 1 failed of 5, in 0.33 s. Python 3.9.6, pytest 8.4.2, fastapi 0.128.8.
| Test | Covers | Result | Note |
|---|---|---|---|
| test_get_order_ok | GET /orders/A-1001 | pass | Checks status and id only. Never looks at total. |
| test_get_order_missing | GET /orders/nope | pass | 404 path. |
| test_total_two_lines | order_total(A-1002) | fail | The only test that asserts a real total. |
| test_empty_order_total_is_zero | order_total(B-2001) | pass | Passes with any operator. Zero lines means zero either way. |
| test_account_total | GET /accounts/Account A/total | pass | Asserts orders == 2. Never asserts total. |
The failure, as pytest printed it
FAILED tests/test_orders.py::test_total_two_lines
def test_total_two_lines():
> assert order_total(ORDERS["A-1002"]) == 10 * 45.0 + 1 * 1200.0
E AssertionError: assert 1256.0 == ((10 * 45.0) + (1 * 1200.0))
E + where 1256.0 = order_total({'account': 'Account A', 'id': 'A-1002',
E 'lines': [{'qty': 10, 'sku': 'MA-PRO', 'unit': 45.0}, {'qty': 1, 'sku': 'GIS-STD', 'unit': 1200.0}]})
1 failed, 4 passed in 0.33s
Read it as: 10 + 45 + 1 + 1200 = 1256. The code adds where it should multiply.
Top three risks, ranked
total += line["qty"] + line["unit"] adds quantity to unit price. This is the bug the README hides on purpose, and test_total_two_lines is the test that catches it. Downstream, the account endpoint sums the wrong numbers, so it is wrong too and its test still passes.
| Object | Reported | Correct | Gap |
|---|---|---|---|
| /orders/A-1001 | 1202.00 | 2400.00 | -1198.00 |
| /orders/A-1002 | 1256.00 | 1650.00 | -394.00 |
| /accounts/Account A/total | 2458.00 | 4050.00 | -1592.00 |
| /orders/B-2001 | 0.00 | 0.00 | 0.00 |
test_account_total asserts the order count and stops. test_empty_order_total_is_zero at line 22 passes whatever operator is on line 17. Delete test_total_two_lines and the suite goes green with the bug still in. The aggregation endpoint has no value assertion at all.
ORDERS is a plain dict at import time. It is shared by every request and by the tests that import it, resets on restart, and the account route scans it linearly with case-sensitive equality, so account a is a 404. There are no Pydantic response models, so the JSON shape is whatever the dict holds.
Proposed fix for risk 1
One character. Applied to a scratch copy and re-run: 5 passed in 0.22 s. After the fix, A-1001 returns 2400.0 and Account A returns 4050.0.
@@ -14,7 +14,7 @@ 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)
Follow-up for risk 2, not applied: make test_account_total assert r.json()["total"] == 4050.0 so the aggregation path is covered by value, not just by count.
Probe an order
Type an order id. The page recomputes the total both ways from the same three orders the service holds, so you can check the arithmetic by hand.