0%

Plan, Build, and Test Programs · practice

Build and Test One Piece at a Time

A plan can still feel large when you try to implement every step at once. Build a thin, working instead.

For this focused scorer, assume each response is already non-empty. The "missing" result from the previous lesson belongs to the later input-and-retry step. Here, the scorer can concentrate on comparing valid response text.

The quiz engine needs to ignore capitalization and surrounding spaces. Start with the smallest reusable behavior:

def clean_answer(text):
    return text.strip().lower()

Check it immediately:

assert clean_answer("  BLUE ") == "blue"

Then build the next piece:

def answers_match(given, expected):
    return clean_answer(given) == clean_answer(expected)

Check that independently:

assert answers_match(" BLUE ", "blue") is True
assert answers_match("blue whale", "whale") is False

Only then use it inside the scoring :

def score_responses(responses):
    score = 0

    for response in responses:
        if answers_match(response["given"], response["expected"]):
            score += 1

    return score

Small checks narrow failures

If the final score is wrong but both helper checks pass, the likely problem is in the scoring loop. If the cleaning check fails, there is no reason to debug the loop yet.

Each completed piece reduces the area you need to inspect.

Build in dependency order

Start with that do not depend on your other functions:

clean one answer
compare two cleaned answers
count matching response records
format the score

This creates a natural sequence. Later functions can rely on earlier behavior that already has evidence behind it.

Keep the program runnable

After each small change:

  1. run the focused checks;

  2. run one end-to-end example;

  3. save or keep the working state;

  4. add the next behavior.

A half-hour rewrite followed by one final run creates many possible causes at once. Frequent small runs make debugging cheaper and considerably less dramatic.

Stubs can hold a place

During planning, a function body can temporarily contain pass:

def score_responses(responses):
    pass

This lets you name the boundary and sketch the caller. Replace the stub before relying on its result. A stub is a marker for unfinished work, not a successful implementation.

A quiz score depends on cleaning text and comparing cleaned values. Which build order gives the clearest feedback?

Task

Build a quiz scorer in dependency order.

  1. Implement clean_answer(text) so it strips surrounding whitespace and ignores capitalization.

  2. Implement answers_match(given, expected) so it uses clean_answer and returns a .

  3. Implement score_responses(responses) so it returns one point for every matching "given" and "expected" pair.

Keep the focused assertions that follow each . Work from the top: make one function and its checks pass before moving to the next. Keep the prepared responses and final print.

The responses deliberately include spaces, capitalization differences, and one wrong answer. The final output must be:

Score: 2/3