🎯 Hands-on Portfolio Deliverable: Execute a structured AI-assisted root cause analysis on non-deterministic and logic bugs, refactor the code for testability, and author rock-solid regression tests.
The brief
Practice the structured debug-with-AI workflow on a non-trivial bug. Find the bug, fix it, write a regression test.
Choose your primary bug
Choose one primary bug: either a real bug from your work or open source, or the sample below. Your own bug replaces the sample; it does not need to use aggregate_clicks or its function signature. In addition, complete exercises A, B and C below for either choice.
Sample: click aggregation
This sample uses naive UTC datetimes consistently. Define the last-24-hour window as cutoff < timestamp ≤ now: an event exactly at the cutoff is excluded, an event at now is included, and future events are excluded.
from datetime import datetime, timedelta
from collections import defaultdict
def aggregate_clicks(clicks: list[dict]) -> dict[str, int]:
cutoff = datetime.utcnow() - timedelta(hours=24)
counts = defaultdict(int)
for click in clicks:
if click['timestamp'] > cutoff: # BUG: future events are included
counts[click['url']] += 1
return dict(counts)
Reproduce with a controlled clock
Save the sample as buggy.py. Run this pytest test against the original function. It should fail because /future is included:
from datetime import datetime
from unittest.mock import patch
from buggy import aggregate_clicks
def test_window_excludes_future_events():
clicks = [
{'url': '/inside', 'timestamp': datetime(2026, 5, 27, 10)},
{'url': '/future', 'timestamp': datetime(2026, 5, 27, 13)},
]
with patch('buggy.datetime') as clock:
clock.utcnow.return_value = datetime(2026, 5, 27, 12)
assert aggregate_clicks(clicks) == {'/inside': 1}
The hidden system clock makes the original code hard to test. The missing upper bound is the actual logic bug. An empty result when running these old sample dates today can be correct; it is not, by itself, proof of a bug.
Discuss, fix and test
Ask the AI to trace the input against the stated window. Make the clock controllable, for example with an optional now parameter, and enforce cutoff < click['timestamp'] <= now. Keep existing callers working where practical. Write deterministic tests for an event inside the window, exactly at cutoff, exactly at now, in the future, and older than the window. Use the same timezone convention throughout.
Record the reproduction, root cause, fix, tests, and how AI helped in DEBUG.md. If using your own primary bug, document and test that bug instead; the sample's code and signature are not required.
More debug exercises
Apply the same workflow to:
Exercise A: Off-by-one
def get_page(items: list, page: int, page_size: int = 10) -> list:
start = page * page_size # page is zero-based
end = start + page_size
return items[start:end + 1] # bug: extra item
Bug: returns 11 items, not 10.
Exercise B: Wrong operator
def is_admin_or_owner(user, resource) -> bool:
return user.is_admin or user.id == resource.owner_id and user.is_active
# bug: precedence; `is_active` only checked on owner, not admin
Bug: admin without is_active still passes.
Exercise C: Edge case
def average(nums: list[float]) -> float:
return sum(nums) / len(nums)
# bug: empty list = ZeroDivisionError
Define the desired contract: raise ValueError for an empty list with a clear message; test both empty and nonempty input.
For each: reproduce → discuss with AI → identify → fix → test.
Deliverables
- The chosen primary bug and each of exercises A, B, and C reproduced and fixed.
- Regression test per bug.
- A
DEBUG.mddocumenting:- The original bug behavior.
- Steps to reproduce.
- Root cause.
- Fix.
- How AI helped (or didn't).
What you'll learn
- Structured debug-with-AI workflow.
- The importance of reproduction.
- Identifying root causes vs symptoms.
- Writing regression tests.
- When AI debugging shines and when it stumbles.
Stretch
- Bring 5 real bugs from your work or open-source; debug each with AI.
- For each: time spent without AI vs with AI estimate.
📊 100-Point Evaluation Rubric
| Evaluation Dimension | Weight | Target Standard (Pass ≥ 80%) |
|---|---|---|
| 1. Reproduction & Root Cause Analysis | 25 pts | Clear isolation of non-deterministic behavior (e.g. datetime.utcnow() clock dependency) and logical flaws rather than patching symptoms. |
| 2. Fix Quality & Determinism | 25 pts | Implemented clean architectural solution (e.g. dependency injection of now timestamp or fixed window parameters) preserving existing callers where practical. |
| 3. Regression Test Fixtures | 25 pts | Deterministic pytest regression test that locks in expected behavior and prevents regressions regardless of execution environment or clock time. |
| 4. Multi-Bug Analysis & DEBUG.md | 25 pts | Completed DEBUG.md covering root cause analysis, fix documentation, and solutions for exercises A, B, and C. A learner-selected primary bug can replace the sample. |
📤 Submission Instructions & Guidelines
- Deliverable Formats:
- Option A (Recommended): Upload a single
.ziparchive containing your fixed Python scripts, pytest regression tests, andDEBUG.md. - Option B: Upload your
DEBUG.mdand paste your GitHub Gist or repo link in the Submission Notes box below.
- Option A (Recommended): Upload a single
- Pre-Submission Verification:
- Run
pytestto confirm your regression tests pass consistently across multiple runs. - Review your
DEBUG.mdto ensure root cause explanations are clear and complete.
- Run
- Submit Your Work:
- Upload your file via the dropzone below and click Submit Assignment.