TP6 - AI-Assisted Code Generation and Debugging
Lab Overview
In this lab, you will use AI coding assistants (GitHub Copilot, ChatGPT, Claude, or Cursor) to perform real-world development tasks. The goal is not to blindly accept AI output — it is to learn how to prompt effectively, review critically, and improve iteratively.
Learning Objectives
By the end of this lab, you will be able to:
- Write effective prompts for code generation tasks
- Review and fix AI-generated code for correctness and security
- Use AI to debug broken code systematically
- Leverage AI for refactoring and performance improvement
- Generate tests with AI and validate their coverage
- Reflect critically on AI strengths and limitations
Prerequisites
- Python 3.10+ installed
- Access to at least one AI coding tool (ChatGPT, Copilot, Claude, or Cursor)
- Familiarity with FastAPI, pandas, and pytest
- Completed Module 4 concepts and prompt engineering readings
Tools Needed
| Tool | Purpose | Required? |
|---|---|---|
| ChatGPT / Claude | Conversational code generation | At least one |
| VS Code + Copilot or Cursor | Inline AI assistance | Recommended |
| Python 3.10+ | Running and testing code | Required |
| pip | Installing dependencies | Required |
Setup
Create a project directory and virtual environment:
mkdir tp6-ai-coding && cd tp6-ai-coding
python -m venv venv
# Windows
venv\Scripts\activate
# macOS/Linux
source venv/bin/activate
pip install fastapi uvicorn pandas scikit-learn pytest httpx bandit
Exercise 1: AI-Generated Data Preprocessing (15 min)
Objective
Use AI to generate a data preprocessing function, then review and improve it.
Step 1: Write Your Prompt
Use the following prompt with your AI tool of choice. Do not modify it — we want to see what the AI generates from a standard prompt:
Write a Python function called `preprocess_customer_data` that:
- Accepts a pandas DataFrame with columns:
customer_id (int), name (str), email (str), age (int),
annual_income (float), signup_date (str in YYYY-MM-DD format)
- Performs the following preprocessing:
1. Remove duplicate rows based on customer_id
2. Handle missing values: fill age with median, income with mean,
drop rows where email is missing
3. Validate email format (must contain @ and .)
4. Convert signup_date to datetime
5. Add a column "account_age_days" = days since signup
6. Remove outliers in annual_income (outside 1.5 * IQR)
7. Normalize annual_income to 0-1 range
- Returns the cleaned DataFrame
- Include type hints and a docstring
- Raise ValueError for invalid input (empty DataFrame, missing required columns)
Step 2: Review the Generated Code
Copy the AI's output into a file called preprocessing.py. Now review it using the REVIEW checklist:
| Check | Question | Your Notes |
|---|---|---|
| R - Readability | Is the code clean, well-named, and documented? | |
| E - Edge cases | What happens with empty DataFrame? All NaN column? | |
| V - Vulnerabilities | Any security issues (unlikely here, but check)? | |
| I - Integration | Would this fit in a production data pipeline? | |
| E - Efficiency | Any unnecessary copies or redundant operations? | |
| W - Working | Does it actually run without errors? |
Step 3: Test the Function
Create a test file test_preprocessing.py and write at least 3 tests manually (before asking AI):
import pandas as pd
import pytest
from preprocessing import preprocess_customer_data
def test_basic_preprocessing():
"""Test with clean, valid data."""
df = pd.DataFrame({
"customer_id": [1, 2, 3],
"name": ["Alice", "Bob", "Charlie"],
"email": ["alice@test.com", "bob@test.com", "charlie@test.com"],
"age": [25, 30, 35],
"annual_income": [50000.0, 60000.0, 70000.0],
"signup_date": ["2024-01-15", "2024-03-20", "2024-06-10"],
})
result = preprocess_customer_data(df)
assert len(result) == 3
assert "account_age_days" in result.columns
assert result["annual_income"].min() >= 0
assert result["annual_income"].max() <= 1
def test_empty_dataframe():
"""Test with empty DataFrame — should raise ValueError."""
df = pd.DataFrame()
with pytest.raises(ValueError):
preprocess_customer_data(df)
def test_duplicate_removal():
"""Test that duplicates on customer_id are removed."""
df = pd.DataFrame({
"customer_id": [1, 1, 2],
"name": ["Alice", "Alice", "Bob"],
"email": ["a@test.com", "a@test.com", "b@test.com"],
"age": [25, 25, 30],
"annual_income": [50000.0, 50000.0, 60000.0],
"signup_date": ["2024-01-15", "2024-01-15", "2024-03-20"],
})
result = preprocess_customer_data(df)
assert len(result) == 2
Run the tests:
pytest test_preprocessing.py -v
Step 4: Fix Any Issues
If tests fail, fix the AI-generated code. Document what you changed and why.
Exercise 2: Debugging a Broken API Endpoint (15 min)
Objective
Use AI to identify and fix bugs in a broken FastAPI endpoint.
The Buggy Code
Create a file called buggy_api.py with the following code. It has 5 intentional bugs — your job is to use AI to find and fix them all:
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import json
app = FastAPI()
# Bug 1: Mutable default argument
users_db = []
class User(BaseModel):
name: str
email: str
age: int
class UserResponse(BaseModel):
id: int
name: str
email: str
age: int
# Bug 2: Global mutable counter (not thread-safe)
next_id = 0
@app.post("/users", response_model=UserResponse)
def create_user(user: User):
global next_id
next_id =+ 1 # Bug 3: Operator error (=+ instead of +=)
new_user = {
"id": next_id,
"name": user.name,
"email": user.email,
"age": user.age,
}
users_db.append(new_user)
return new_user
@app.get("/users/{user_id}", response_model=UserResponse)
def get_user(user_id: int):
# Bug 4: Wrong comparison (comparing index, not id)
if user_id < len(users_db):
return users_db[user_id]
raise HTTPException(status_code=404, detail="User not found")
@app.get("/users", response_model=list[UserResponse])
def list_users(min_age: int = None):
if min_age: # Bug 5: Falsy check fails when min_age=0
return [u for u in users_db if u["age"] >= min_age]
return users_db
@app.delete("/users/{user_id}")
def delete_user(user_id: str): # Bug 6 (bonus): wrong type hint
global users_db
users_db = [u for u in users_db if u["id"] != user_id] # Type mismatch
return {"message": "Deleted"}
Step 1: Try the AI Debugging Prompt
Use this prompt with your AI tool:
I have a FastAPI application with several bugs. Please:
1. Identify ALL bugs in the code
2. Explain what each bug does and why it's a problem
3. Provide the corrected code
4. Suggest additional improvements for production readiness
Here is the code:
[paste the buggy code above]
Step 2: Verify the AI's Analysis
| Bug # | Did AI Find It? | AI's Explanation Correct? | Your Notes |
|---|---|---|---|
| Bug 1 (mutable default) | Yes / No | Yes / No | |
| Bug 2 (thread safety) | Yes / No | Yes / No | |
| Bug 3 (=+ operator) | Yes / No | Yes / No | |
| Bug 4 (wrong lookup) | Yes / No | Yes / No | |
| Bug 5 (falsy check) | Yes / No | Yes / No | |
| Bug 6 (type mismatch) | Yes / No | Yes / No |
Step 3: Apply the Fixes
Create fixed_api.py with the corrected code. Run it and test manually:
uvicorn fixed_api:app --reload
# Test with curl or httpx
curl -X POST http://localhost:8000/users \
-H "Content-Type: application/json" \
-d '{"name": "Alice", "email": "alice@test.com", "age": 25}'
Exercise 3: AI-Assisted Refactoring (10 min)
Objective
Use AI to refactor a poorly-written function for better readability and performance.
The Messy Code
Create a file called messy_code.py:
def process(d):
r = []
for i in range(len(d)):
if d[i]['status'] == 'active' and d[i]['age'] >= 18:
if d[i]['email'] != None and d[i]['email'] != '':
x = {}
x['name'] = d[i]['first_name'] + ' ' + d[i]['last_name']
x['email'] = d[i]['email'].lower().strip()
x['category'] = ''
if d[i]['age'] >= 18 and d[i]['age'] < 25:
x['category'] = 'young_adult'
elif d[i]['age'] >= 25 and d[i]['age'] < 35:
x['category'] = 'adult'
elif d[i]['age'] >= 35 and d[i]['age'] < 50:
x['category'] = 'middle_aged'
elif d[i]['age'] >= 50:
x['category'] = 'senior'
x['score'] = d[i]['purchases'] * 10 + d[i]['reviews'] * 5 + d[i]['referrals'] * 20
if x['score'] > 100:
x['tier'] = 'gold'
elif x['score'] > 50:
x['tier'] = 'silver'
else:
x['tier'] = 'bronze'
r.append(x)
return r
Your Prompt
Write a prompt that asks the AI to refactor this code. Your prompt should request:
- Meaningful variable and function names
- Type hints and a docstring
- Use of Pydantic models for input/output
- Extraction of the categorization and scoring logic into helper functions
- Use of list comprehension or
filter()where appropriate
Evaluation
Compare the AI's refactored version against this checklist:
- Function has a descriptive name
- Parameters have type hints
- Return type is specified
- Docstring explains purpose, args, and returns
- Variable names are descriptive
- Logic is broken into smaller functions
- No repeated conditions
- Uses Pydantic or dataclasses for structure
Exercise 4: AI-Generated Unit Tests (10 min)
Objective
Use AI to generate a comprehensive test suite, then evaluate its quality.
The Function to Test
Use your refactored code from Exercise 3 (or the original process function if you prefer).
Your Prompt
Write a comprehensive pytest test suite for the following function.
Include:
1. Happy path tests (normal valid input)
2. Edge cases (empty list, single item, all filtered out)
3. Boundary tests (age exactly 18, 25, 35, 50)
4. Score boundary tests (score exactly 50, 100)
5. Invalid input handling (missing keys, wrong types)
6. Use @pytest.mark.parametrize for boundary tests
[paste your function here]
Evaluate the Tests
| Criterion | AI's Tests | Your Assessment |
|---|---|---|
| Coverage | What % of code paths are tested? | |
| Edge cases | Are empty inputs and boundaries covered? | |
| Assertions | Are assertions specific and meaningful? | |
| Independence | Do tests run independently (no shared state)? | |
| Naming | Do test names describe the scenario? | |
| Redundancy | Are there duplicate or overlapping tests? |
Run the tests:
pytest test_refactored.py -v --tb=short
Exercise 5: Security Scan (5 min)
Objective
Run a security scan on all AI-generated code from this lab.
Run Bandit
# Scan all Python files in the project
bandit -r . -ll
# If Bandit finds issues, document them:
bandit -r . -f json -o security_report.json
Document Findings
| File | Issue | Severity | Fixed? |
|---|---|---|---|
Exercise 6: Reflection Report (5 min)
Objective
Write a short reflection on your experience using AI coding tools. This develops your critical thinking about AI as a development tool.
Reflection Template
Copy this template and fill it in:
# TP6 Reflection Report
## Student: [Your Name]
## Date: [Date]
## 1. AI Tool(s) Used
- Tool: [e.g., ChatGPT, Copilot, Claude, Cursor]
- Model: [e.g., GPT-4o, Claude 3.5 Sonnet]
## 2. What AI Did Well
- [List 3 specific things the AI handled effectively]
- Example:
- Example:
- Example:
## 3. What AI Got Wrong
- [List 3 specific errors or issues you found]
- Example:
- Example:
- Example:
## 4. Prompt Engineering Insights
- Best prompt strategy I used: [zero-shot / few-shot / CoT]
- Most effective prompt technique: [describe]
- A prompt that didn't work well: [describe and explain why]
## 5. Time Analysis
| Task | Estimated Without AI | Actual With AI | Time Saved |
|------|---------------------|----------------|------------|
| Data preprocessing function | | | |
| Debugging API | | | |
| Refactoring | | | |
| Writing tests | | | |
## 6. Security Findings
- Number of vulnerabilities found by Bandit: [N]
- Most critical issue: [describe]
- Were any vulnerabilities in AI-generated code? [Yes/No — describe]
## 7. Key Takeaways
1. [Most important lesson learned]
2. [How will you use AI tools differently going forward?]
3. [What should you always do manually, even with AI?]
Submission Checklist
Before submitting, verify you have:
-
preprocessing.py— AI-generated + your fixes (Exercise 1) -
test_preprocessing.py— Your manual tests (Exercise 1) -
buggy_api.py— Original buggy code (Exercise 2) -
fixed_api.py— Corrected code with all bugs fixed (Exercise 2) - Bug analysis table documenting what AI found vs. missed (Exercise 2)
-
refactored_code.py— Refactored version of messy code (Exercise 3) -
test_refactored.py— AI-generated test suite (Exercise 4) -
security_report.json— Bandit scan results (Exercise 5) -
reflection.md— Your reflection report (Exercise 6)
Grading Rubric
| Criterion | Points | Description |
|---|---|---|
| Code Generation | 20 | Quality of prompts and generated code |
| Code Review | 20 | Thorough identification and fixing of issues |
| Debugging | 20 | All bugs found and correctly fixed |
| Refactoring | 15 | Clean, well-structured refactored code |
| Testing | 15 | Comprehensive tests with good coverage |
| Reflection | 10 | Thoughtful analysis of AI strengths/weaknesses |
| Total | 100 |