# The week of Harvard's free Python course that matters most for FDEs

> Week 5 of CS50P teaches assert, pytest and packaging, the baseline for code that runs on client data and that someone else will inherit.

Original: https://fdetimes.net/en/books-courses/harvard-cs50p-python-unit-testing/

The CS50P syllabus is numbered from week 0 to week 9. For anyone who wants to become an FDE, the week that deserves the most attention is not OOP or libraries but week 5, where David J. Malan teaches `assert`, `AssertionError`, `pytest` and how to bundle code into a package with `__init__.py`.

The reason is the job itself. Code you write at a client site will run on data you did not create, and someone else will have to take it over once you have left the project.

So a Python foundation with tests and proper error handling is the minimum requirement for an FDE, not a bonus. CS50P teaches exactly that foundation.

## Who teaches it, and how does it work?

The full name is CS50's Introduction to Programming with Python, and the official site is cs50.harvard.edu/python. Harvard describes Malan as Gordon McKay Professor of the Practice of Computer Science. He has taught CS50 since 2007.

According to Harvard PLL, the course lasts 9 weeks, is self-paced, and takes 3–9 hours a week. There are ten lectures, numbered 0 to 9. The materials are free to watch on OpenCourseWare; to earn a certificate, free or paid, you need an edX account.

No programming experience is required, and you do not have to prove you have taken any earlier course. The current run started on 1 January 2026, with a single final deadline of 30 June 2027 and no deadlines for individual assignments.

One point to watch: when a new version is released, work submitted for the old version may not count. Do not leave it half-finished into next year.

## Ten lectures that add up to a familiar FDE task

The ten lectures cover functions and variables, conditionals, loops, exceptions, libraries, unit tests, File I/O, regex, OOP and an Et Cetera session, followed by the final project. Read week by week, it is a familiar list. Put together, it maps onto a very ordinary FDE task.

Imagine a client sends you a CSV exported from a legacy system. The date column has "2026-03-01" in some places, "01/03/2026" in others, and a few rows contain words instead of dates.

To handle this file you need File I/O (week 6) to read it, regex (week 7) to recognise the two formats, and exceptions (week 3) to deal with broken rows without crashing the program.

```python
import re

def parse_date(s):
    if m := re.fullmatch(r"(\d{4})-(\d{2})-(\d{2})", s):
        y, mo, d = m.groups()
    elif m := re.fullmatch(r"(\d{2})/(\d{2})/(\d{4})", s):
        d, mo, y = m.groups()
    else:
        raise ValueError(f"Invalid date: {s}")
    return f"{y}-{mo}-{d}"
```

The remaining step is week 5: write tests that pin down how this function must behave before you run it on real data.

```python
import pytest
from parse import parse_date

def test_two_formats():
    assert parse_date("2026-03-01") == "2026-03-01"
    assert parse_date("01/03/2026") == "2026-03-01"

def test_bad_input():
    with pytest.raises(ValueError):
        parse_date("yesterday")
```

(The Vietnamese strings mean "invalid date", "two formats", "broken row" and "yesterday".)

## A common mistake: the regex matches, but the date is still wrong

Both tests pass, but the function still has a hole. Feed it "99/99/2026" and the regex matches happily, because `\d{2}` only checks for two digits, and the function returns "2026-99-99" as if it were a real date.

This is a classic beginner's regex error: regex checks the shape of a string, not its meaning. The fix is to let the standard library validate the date, then write a test for exactly the case that slipped through.

```python
import re
from datetime import date

def parse_date(s):
    if m := re.fullmatch(r"(\d{4})-(\d{2})-(\d{2})", s):
        y, mo, d = m.groups()
    elif m := re.fullmatch(r"(\d{2})/(\d{2})/(\d{4})", s):
        d, mo, y = m.groups()
    else:
        raise ValueError(f"Invalid date: {s}")
    date(int(y), int(mo), int(d))  # new line: raises ValueError if the date doesn't exist
    return f"{y}-{mo}-{d}"
```

The new line raises `ValueError` if the date does not exist. And here is a new test for the case that slipped through:

```python
def test_nonexistent_date():
    with pytest.raises(ValueError):
        parse_date("99/99/2026")
```

An exercise: the client has just sent more rows like "1/3/2026", without leading zeros. Write the test first, expecting "2026-03-01", add a test that makes sure "31/02/2026" is rejected, and only then change the regex and the output formatting until every test passes.

**Key point:** Code that runs on your machine will not necessarily work on the client's data.

## Three ideas to take away from the course

First: errors are normal. The course's week 0 lecture notes say bugs are a natural part of programming, problems for you to solve, and encourage learners not to get discouraged.

For an FDE, that advice has a more specific meaning: bad data will always turn up, so the `raise ValueError` above is a design decision, not a temporary patch.

Second: tests are an agreement with yourself and with whoever takes over the code. The tests above describe exactly what the function accepts and what it rejects. When the client sends a new format, you add an `assert` line before changing the code, so you know for certain you have not broken the old formats.

Third: code you leave for others must be packaged. Week 4 teaches how to use libraries; week 5 teaches how to build your own package with `__init__.py`. A script sitting in a Downloads folder is very different from a package that the client's engineers can import and test after you have left the project.

## Who should take it, and in what order?

If you have 2-8 years of experience with Java, C# or JavaScript, you can skim weeks 0–2 in an evening or two.

Save your time for weeks 3, 5, 6 and 7, and do every problem set in those weeks, including the ones that look easy.

Beginners should follow the order as given, since the course is designed for people who have never programmed.

The final project is where to invest most. Pick a problem that resembles real client work, such as a tool for cleaning export files like the example above, with a test folder and a README explaining how to run it. On your CV, describe it as a project ("handles N data formats, tested with pytest"), not just the course name.

On certificates, CS50 issues its own certificate free of charge. There is also a paid verified certificate on edX that you can use as evidence for employers.

Whichever you choose, when applying for FDE roles treat the project repo as your main evidence and the certificate as secondary. Let the `tests/` folder speak for you.

CS50P will not turn you into an FDE. What it can do is make sure that the first time a client hands you a messy data file, your first reflex is to write a test, not to run it and hope.

**Try this week:**

- Open cs50.harvard.edu/python, create an edX account if you want a certificate, and skim weeks 0–2 in one evening.
- Write a parse_date function that accepts two date formats, with two pytest tests: one for valid input, one for bad data.
- Choose a final project topic modelled on a real client problem, such as a tool for cleaning export files from a legacy system.

## Sources

- [CS50's Introduction to Programming with Python | Harvard PLL](https://pll.harvard.edu/course/cs50s-introduction-programming-python)

- [CS50's Introduction to Programming with Python (CS50P)](https://cs50.harvard.edu/python/)

- [CS50's Introduction to Programming with Python (CS50P)](https://cs50.harvard.edu/python/2022/)

- [CS50P FAQs](https://cs50.harvard.edu/python/faqs/)

- [CS50P Lecture 0 notes](https://cs50.harvard.edu/python/notes/0/)

- [CS50P Week 5](https://cs50.harvard.edu/python/2022/weeks/5/)

- [CS50 - Wikipedia](https://en.wikipedia.org/wiki/CS50)
