Module 1 · Software Developer Capstone: Fix It Properly
The codebase and the bug list
Join Kasuwa's refunds team, get the service running, read its code and its (passing) tests, and triage six bug reports by the harm each one does.
About 25 minutes
The problem
This is the capstone of the Software Developer track. Instead of writing code from a blank page, you'll do what most developers spend most of their time doing: working on someone else's code, with real bugs reported by real people.
You've joined Kasuwa, the online shop from the other capstones, on the team that owns the refunds service. When a delivery fails or a customer returns something, this service works out the refund and records it. Its tests all pass, yet in the last week support, finance, the mobile team and a security review have between them reported six problems. Your lead says: "Sort these out properly. Tests first, no guessing, and nothing that makes it worse."
Every lesson starts from the original code in a new Colab notebook, so each one stands on its own. In the final project, you'll combine all the fixes in one repository.
The concept
Read before you change
Find the entry points (the API in app.py), the rules (refunds.py) and the data access (db.py, schema.sql). Run the tests. Passing tests only prove what they test.
Triage by harm
| Priority | Kind of bug | Why |
|---|---|---|
| 1 | Security: data exposed or changed by the wrong person | Harms every customer, and the harm can't be undone |
| 2 | Money: paying out too much or too little | Real losses, and customers' trust |
| 3 | Customers wrongly refused or confused | Unfair, and generates complaints |
| 4 | Errors with no lasting harm | Fix, but after the above |
Every bug gets a test
For each bug: reproduce it with a failing test, fix it, and keep the test so it can't come back.
Example
Get the code and the sample data:
Shell (bash)
%%bash
base=https://academy.cloudtechanalytics.com/datasets/refunds
for f in refunds.py db.py app.py schema.sql customers.csv orders.csv order_items.csv issues.csv test_refunds.py pytest.ini pr-42.diff; do
curl -sO "$base/$f"
done
lsapp.py
customers.csv
db.py
issues.csv
order_items.csv
orders.csv
pr-42.diff
pytest.ini
refunds.py
schema.sql
test_refunds.pyRun the existing tests:
Shell (bash)
%%bash
python -m pytest...
3 passed in 0.01sAll three pass. Now the bug reports:
Shell (bash)
%%bash
python - <<'EOF'
import csv
for issue in csv.DictReader(open("issues.csv", encoding="utf-8")):
print(f"{issue['issue_id']} {issue['reported_by']:17} {issue['title']}")
EOFISSUE-101 Customer support Refund is a kobo short
ISSUE-102 Finance Customer refunded twice
ISSUE-103 Customer support Return on day 14 rejected
ISSUE-104 Security review Order search shows other customers' orders
ISSUE-105 Finance Refunds add up to more than the order
ISSUE-106 Mobile team Server error for a missing orderAnd a look at the rules everyone depends on:
Shell (bash)
%%bash
sed -n '9,26p' refunds.pydef item_refund(quantity, unit_price_kobo, reason):
"""Refund for one order line, in kobo."""
naira = quantity * (unit_price_kobo / 100)
if reason == "changed_mind":
naira = naira * (1 - RESTOCKING_FEE)
return int(naira * 100)
def within_window(delivered_on, today):
"""True if a return is still allowed: within 14 days of delivery."""
return (today - delivered_on).days < RETURN_WINDOW_DAYS
def refund_amount(items, reason, delivery_fee_kobo):
"""Total refund in kobo. items is a list of (quantity, unit_price_kobo) pairs."""
total = sum(item_refund(quantity, price, reason) for quantity, price in items)
if reason in ("failed_delivery", "damaged", "wrong_item"):
total += delivery_fee_koboThree things stand out before you even run anything: money passes through floats in naira, the window check uses < against 14 days, and int() cuts off fractions rather than rounding. The tests never exercise any of them.
Walkthrough
- Run the cells in a new Colab notebook.
- Read
db.pyandapp.py. Which line looks unsafe to you, before reading any bug report? - Read every issue's full description (
issues.csv). For each, guess which file the bug is in. - Start the service in a Python cell with the Flask test client and post one refund, to see it working.
- Write the triage (the task below).
Practice
Practice
How many tests does the service have, and pass, before you change anything?
Task
8 minWrite the triage: all six issues in the order you'll fix them, each with a one-line reason (its kind of harm).
Your work is checked for
- Lists all six issues
- Security first (ISSUE-104 in first place)
- Gives reasons (security, money, customers)
- The 500 error comes last (ISSUE-106)
Check your understanding
Answer every question to check.