Lab 010: GitHub Copilot β First StepsΒΆ
What You'll LearnΒΆ
- Use inline code completion to write code from comments
- Use Copilot Chat
/fixto find and understand real bugs - Use Copilot Edits to refactor an entire file with natural language
- Use inline chat to extend code without leaving the editor
- Write prompts that get better results
This lab uses hands-on exercises β you'll open files with real bugs and incomplete code, then use Copilot to fix and extend them.
PrerequisitesΒΆ
1. Enable GitHub Copilot FreeΒΆ
- Go to github.com/features/copilot β "Start for free"
- Sign in and follow the setup wizard
Students get Copilot Pro for free
2. Install VS Code + Copilot extensionΒΆ
- Install VS Code
- Extensions (
Ctrl+Shift+X) β search "GitHub Copilot" β Install both: - GitHub Copilot (completions)
- GitHub Copilot Chat (chat panel)
- Sign in when prompted β you'll see the Copilot icon in the status bar
3. Download the exercise filesΒΆ
Clone or download the exercise files for this lab:
Or copy each file directly from the sections below.
π¦ Supporting FilesΒΆ
Download these files before starting the lab
Save all files to a lab-010/ folder in your working directory.
| File | Description | Download |
|---|---|---|
exercise1_fibonacci.py |
Interactive exercise script | π₯ Download |
exercise2_shopping_cart.py |
Interactive exercise script | π₯ Download |
exercise3_product_search.py |
Interactive exercise script | π₯ Download |
exercise4_refactor_me.py |
Interactive exercise script | π₯ Download |
Exercise 1 β Inline Completion: Write Code from CommentsΒΆ
Goal: Learn how Copilot completes code as you type.
Create a new file practice.py and type each comment below. After each comment, stop typing and wait for Copilot's suggestion. Press Tab to accept, you can keep pressing tab until copilot stops suggesting more completions.
We will not execute this code, so don't worry about syntax errors or missing imports β just focus on the suggestions Copilot gives you based on the comments.
# Function that takes a list of prices and returns the average:
# Function that reads a CSV file and returns rows as a list of dicts:
# Async function that fetches JSON from a URL using httpx:
# Class OutdoorProduct with name, price, category attributes and a discount() method:
Keyboard shortcuts
| Key | Action |
|---|---|
Tab |
Accept suggestion |
Esc |
Dismiss |
Alt+] / Alt+[ |
Next / previous suggestion |
Ctrl+Enter |
Open all suggestions panel |
Try better and worse prompts:
| β Vague | β Specific |
|---|---|
# sort this |
# Sort list of dicts by 'price' descending, then 'name' ascending |
# connect to db |
# Connect to PostgreSQL using asyncpg, return a connection pool |
# handle error |
# Retry 3 times with exponential backoff if requests.Timeout is raised |
Exercise 2 β Copilot /fix: Bug Hunt πΒΆ
Goal: Use Copilot Chat to find, understand, and fix real bugs.
File: π₯ exercise1_fibonacci.pyΒΆ
# exercise1_fibonacci.py
# π BUG HUNT β This file has 3 bugs. Can you find them all using Copilot /fix?
#
# TASK: The fibonacci() function should return a list of the first n
# Fibonacci numbers: [0, 1, 1, 2, 3, 5, 8, 13, ...]
#
# EXPECTED OUTPUT (for n=8):
# fibonacci(8) β [0, 1, 1, 2, 3, 5, 8, 13]
# fibonacci(1) β [0]
# fibonacci(0) β []
#
# HOW TO USE THIS EXERCISE:
# 1. Open this file in VS Code
# 2. Select ALL the code (Ctrl+A)
# 3. Open Copilot Chat β type: /fix
# 4. Read Copilot's explanation of each bug
# 5. Accept the fix and run the tests below to verify
def fibonacci(n):
"""Return a list of the first n Fibonacci numbers."""
if n = 0: # BUG 1: syntax error
return []
sequence = [0, 1]
for i in range(2, n):
next_val = sequence[i-1] + sequence[i-2]
sequence.append(next_val)
return sequence[n] # BUG 2: should return a slice, not a single element
# BUG 3: what happens when n=1? sequence has 2 elements but we only want 1
# --- Tests (run after fixing) ---
if __name__ == "__main__":
assert fibonacci(0) == [], f"Expected [], got {fibonacci(0)}"
assert fibonacci(1) == [0], f"Expected [0], got {fibonacci(1)}"
assert fibonacci(8) == [0, 1, 1, 2, 3, 5, 8, 13], f"Got {fibonacci(8)}"
print("β
All tests passed!")
Steps:
- Copy the code above into a new file (or open it from the downloaded exercises)
- Open Copilot Chat (
Ctrl+Shift+I) - Select all the code (
Ctrl+A) - Type:
/fix
Copilot should identify all 3 bugs and explain each one. Before accepting, read the explanation β understanding why the code was wrong is the point.
Expected output after fixing:
Run python exercise1_fibonacci.py β you should see: β
All tests passed!
File: π₯ exercise2_shopping_cart.pyΒΆ
# exercise2_shopping_cart.py
# π BUG HUNT β This file has 4 bugs. Use Copilot Chat to find and fix them.
#
# SCENARIO: OutdoorGear Inc. shopping cart logic.
# The cart should:
# - Add items with a quantity
# - Calculate total price (sum of price Γ quantity)
# - Apply a 10% discount on orders over $200
# - Count unique items (not total quantity)
#
# EXPECTED OUTPUT:
# Cart with 2x TrailBlazer ($189.99) + 1x Summit Tent ($349):
# total before discount = $728.98
# total after 10% discount = $656.08
# unique_items = 2
#
# HOW TO USE:
# 1. Copy this file into VS Code
# 2. Try to run it: python exercise2_shopping_cart.py
# 3. Read the errors β but DON'T fix manually yet!
# 4. Select all code β Copilot Chat β /fix
# 5. Ask Copilot to explain EACH bug before fixing
# 6. Verify with the tests at the bottom
class ShoppingCart:
def __init__(self):
self.items = {} # {product_name: {"price": float, "quantity": int}}
def add_item(self, name: str, price: float, quantity: int = 1):
if name in self.items:
self.items[name]["quantity"] += quantity
else:
self.items[name] = {"price": price, "quantity": quantity}
def get_total(self) -> float:
"""Calculate total price, applying 10% discount if over $200."""
total = 0
for item in self.items: # BUG 1: iterating over keys only, not values
total += item["price"] * item["quantity"]
if total > 200:
total = total * 0.90 # BUG 2: discount calculation correct, but...
# should return rounded to 2 decimal places
return total
def count_unique_items(self) -> int:
"""Return the number of unique products (not total quantity)."""
return sum(self.items.values()) # BUG 3: wrong β should be len(), not sum()
def get_receipt(self) -> str:
lines = []
for name, details in self.items.items():
subtotal = details["price"] + details["quantity"] # BUG 4: + instead of *
lines.append(f" {name} x{details['quantity']} @ ${details['price']:.2f} = ${subtotal:.2f}")
total = self.get_total()
lines.append(f"\nTotal: ${total:.2f}")
return "\n".join(lines)
# --- Tests ---
if __name__ == "__main__":
cart = ShoppingCart()
cart.add_item("TrailBlazer X200", 189.99, 2)
cart.add_item("Summit Pro Tent", 349.00, 1)
total = cart.get_total()
unique = cart.count_unique_items()
print(cart.get_receipt())
print(f"\nUnique items: {unique}")
assert unique == 2, f"Expected 2 unique items, got {unique}"
assert abs(total - 656.08) < 0.01, f"Expected $656.08, got ${total}"
print("\nβ
All tests passed!")
This file has 4 bugs in the ShoppingCart class. This time, before using /fix:
- Try to spot the bugs yourself first β spend 2 minutes reading the code
- Then use Copilot Chat: select all β
/fix - Did Copilot find bugs you missed?
Ask Copilot to explain one bug in depth:
Expected output after fixing:
TrailBlazer X200 x2 @ $189.99 = $379.98
Summit Pro Tent x1 @ $349.00 = $349.00
Total: $656.08
Unique items: 2
β
All tests passed!
Exercise 3 β Inline Chat: Fix + ExtendΒΆ
Goal: Fix bugs AND add a new feature using inline chat (Ctrl+I).
File: π₯ exercise3_product_search.pyΒΆ
# exercise3_product_search.py
# π BUG HUNT + EXTEND β This file has 2 bugs AND is missing a feature.
#
# SCENARIO: OutdoorGear product search with filtering.
#
# TASK A (Fix): Find and fix the 2 bugs using Copilot /fix
# TASK B (Extend): Ask Copilot to add a sort_by_price() function
# Prompt to use: "Add a sort_by_price(products, ascending=True) function
# that sorts the search results by price"
#
# EXPECTED OUTPUT after fixing:
# search("boot") β [{"name": "TrailBlazer X200", "price": 189.99, "category": "footwear"}]
# search("tent") β [{"name": "Summit Pro Tent", "price": 349.00, "category": "camping"}]
# search("xyz") β []
# search("") β all 5 products
#
# HOW TO USE:
# Step 1 β Fix bugs: Select all β Copilot Chat β /fix
# Step 2 β Extend: Ctrl+I (inline chat) β type the prompt above
# Step 3 β Test: Run the tests at the bottom
CATALOG = [
{"name": "TrailBlazer X200", "price": 189.99, "category": "footwear"},
{"name": "Summit Pro Tent", "price": 349.00, "category": "camping"},
{"name": "ClimbTech Pro Harness", "price": 129.99, "category": "climbing"},
{"name": "OmniPack 45L", "price": 279.99, "category": "packs"},
{"name": "StormShell Jacket", "price": 349.00, "category": "clothing"},
]
def search_products(query: str) -> list[dict]:
"""Return products matching query in name or category (case-insensitive)."""
if not query:
return CATALOG
query_lower = query.lower()
results = []
for product in CATALOG:
if query_lower in product["name"].lower or \ # BUG 1: missing () on .lower
query_lower in product["category"].lower():
result.append(product) # BUG 2: wrong variable name (result vs results)
return results
def format_results(products: list[dict]) -> str:
"""Format search results for display."""
if not products:
return "No products found."
lines = [f"Found {len(products)} product(s):"]
for p in products:
lines.append(f" β’ {p['name']} β ${p['price']:.2f} ({p['category']})")
return "\n".join(lines)
# --- Tests ---
if __name__ == "__main__":
print("Test 1: search for 'boot'")
r1 = search_products("boot")
print(format_results(r1))
assert len(r1) == 1 and r1[0]["name"] == "TrailBlazer X200"
print("\nTest 2: search for 'tent'")
r2 = search_products("tent")
print(format_results(r2))
assert len(r2) == 1 and r2[0]["name"] == "Summit Pro Tent"
print("\nTest 3: empty search returns all")
r3 = search_products("")
assert len(r3) == 5
print("\nTest 4: search 'xyz' returns empty")
r4 = search_products("xyz")
assert r4 == []
# Test the sort function Copilot should have added:
print("\nTest 5: sort by price ascending")
sorted_asc = sort_by_price(CATALOG, ascending=True)
assert sorted_asc[0]["name"] == "ClimbTech Pro Harness" # cheapest first
assert sorted_asc[-1]["price"] == 349.00
print("\nβ
All tests passed!")
Part A β Fix (2 bugs):
- Open the file in VS Code
- Select all (
Ctrl+A) β Copilot Chat β/fix - Verify:
python exercise3_product_search.pyβ tests 1β4 should pass
Part B β Extend (1 missing feature):
The file mentions a sort_by_price() function that doesn't exist yet.
- Place your cursor at the end of the file (before the tests section)
- Press
Ctrl+I(inline chat) - Type exactly:
- Review the suggestion and press Accept (
Ctrl+Enter) - Run the tests again β all 5 should pass now
Exercise 4 β Copilot Edits: Refactor an Entire FileΒΆ
Goal: Use Copilot Edits to improve code quality with natural language instructions β without changing behavior.
File: π₯ exercise4_refactor_me.pyΒΆ
# exercise4_refactor_me.py
# βοΈ REFACTORING CHALLENGE β No bugs here, but the code is terrible.
#
# TASK: Use Copilot Edits to improve this code WITHOUT changing its behavior.
#
# TRY THESE COPILOT EDITS PROMPTS (one at a time):
# 1. "Add type hints to all function parameters and return values"
# 2. "Add docstrings following Google style to every function"
# 3. "Replace the magic numbers with named constants at the top of the file"
# 4. "Refactor calculate_shipping to use early return instead of nested ifs"
# 5. "Add input validation: raise ValueError for negative prices or quantities"
#
# After each prompt, review what Copilot changed. Accept or reject with Ctrl+Enter / Ctrl+Backspace.
#
# GOAL: By the end, this code should be production-ready.
STANDARD_SHIPPING = 5.99
EXPRESS_SHIPPING = 14.99
FREE_SHIPPING_THRESHOLD = 75.0
DISCOUNT_THRESHOLD = 200.0
DISCOUNT_RATE = 0.10
def calculate_price(p, q):
return p * q
def calculate_shipping(t):
if t >= 75:
return 0
else:
if t > 50:
return 5.99
else:
return 14.99
def apply_discount(t):
if t > 200:
d = t * 0.10
t = t - d
return round(t, 2)
def order_summary(items):
t = 0
for i in items:
t = t + calculate_price(i[0], i[1])
s = calculate_shipping(t)
t_with_shipping = t + s
final = apply_discount(t_with_shipping)
return {"subtotal": round(t, 2), "shipping": s, "discount_applied": t > 200, "total": final}
# Test β this should still pass after all refactoring
if __name__ == "__main__":
items = [(189.99, 1), (349.00, 1)] # (price, quantity)
result = order_summary(items)
print(result)
assert result["total"] == 489.59, f"Got {result['total']}"
print("β
Refactoring complete β behavior unchanged!")
This code works correctly but is hard to read and maintain. Use Copilot Edits to improve it step by step:
- Open the Copilot Edits panel:
Ctrl+Shift+Iβ click "Open Copilot Edits" (pencil icon) - Click "Add Files" and add
exercise4_refactor_me.py - Run each of these prompts one at a time, reviewing changes before moving on:
Prompt 1:
Prompt 2:
Prompt 3:
Prompt 4:
After each prompt, check that the test at the bottom still passes:
python exercise4_refactor_me.py
# Should still print: β
Refactoring complete β behavior unchanged!
Don't accept everything blindly
Sometimes Copilot adds extra complexity. If a suggestion makes the code harder to read, press Discard (Ctrl+Backspace) and rephrase.
Bonus: Ask Copilot to explain, not just fixΒΆ
Use these prompts on any of the exercise files to deepen your understanding:
What You PracticedΒΆ
| Copilot feature | Exercise | Use case |
|---|---|---|
| Inline completion | Exercise 1 | Write new code from comments |
Chat /fix |
Exercise 2 | Understand and fix bugs |
Inline chat Ctrl+I |
Exercise 3 | Fix + extend in-place |
| Copilot Edits | Exercise 4 | Refactor entire files |
Next StepsΒΆ
- Build a no-code Teams agent: β Lab 011 β Copilot Studio
- Use Agent Mode to build a full feature: β Lab 016 β Copilot Agent Mode
- Use free LLMs in your code: β Lab 013 β GitHub Models