Skip to main content

TP6 - AI-Assisted Code Generation and Debugging

Practical Lab 60 min Intermediate

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:

  1. Write effective prompts for code generation tasks
  2. Review and fix AI-generated code for correctness and security
  3. Use AI to debug broken code systematically
  4. Leverage AI for refactoring and performance improvement
  5. Generate tests with AI and validate their coverage
  6. 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

ToolPurposeRequired?
ChatGPT / ClaudeConversational code generationAt least one
VS Code + Copilot or CursorInline AI assistanceRecommended
Python 3.10+Running and testing codeRequired
pipInstalling dependenciesRequired

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:

CheckQuestionYour Notes
R - ReadabilityIs the code clean, well-named, and documented?
E - Edge casesWhat happens with empty DataFrame? All NaN column?
V - VulnerabilitiesAny security issues (unlikely here, but check)?
I - IntegrationWould this fit in a production data pipeline?
E - EfficiencyAny unnecessary copies or redundant operations?
W - WorkingDoes 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 / NoYes / No
Bug 2 (thread safety)Yes / NoYes / No
Bug 3 (=+ operator)Yes / NoYes / No
Bug 4 (wrong lookup)Yes / NoYes / No
Bug 5 (falsy check)Yes / NoYes / No
Bug 6 (type mismatch)Yes / NoYes / 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:

  1. Meaningful variable and function names
  2. Type hints and a docstring
  3. Use of Pydantic models for input/output
  4. Extraction of the categorization and scoring logic into helper functions
  5. 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

CriterionAI's TestsYour Assessment
CoverageWhat % of code paths are tested?
Edge casesAre empty inputs and boundaries covered?
AssertionsAre assertions specific and meaningful?
IndependenceDo tests run independently (no shared state)?
NamingDo test names describe the scenario?
RedundancyAre 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

FileIssueSeverityFixed?

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

CriterionPointsDescription
Code Generation20Quality of prompts and generated code
Code Review20Thorough identification and fixing of issues
Debugging20All bugs found and correctly fixed
Refactoring15Clean, well-structured refactored code
Testing15Comprehensive tests with good coverage
Reflection10Thoughtful analysis of AI strengths/weaknesses
Total100