1 The Problem
We want the classic word game: ask the player for a noun, a verb, an adjective, and so on, then slot their words into a pre-written story. The result is usually hilarious. It teaches collecting several inputs and building a string from pieces.
2 How to Think About It
The plan, before any code:
3 The Build — explained part by part
Here is the complete Mad Libs game. Each line is explained below.
# Collect some words from the player.
name = input("Enter a name: ")
place = input("Enter a place: ")
verb = input("Enter a verb (an action): ")
adjective = input("Enter an adjective (a describing word): ")
# Slot the words into a story template.
story = f"""
One day, {name} decided to visit {place}.
On the way, they could not stop {verb}!
Everyone agreed it was the most {adjective} day ever.
"""
print(story)
name. We do this once for each word the story needs.The triple-quoted f-string (
f"""…""") — triple quotes let a piece of text span several lines. The f at the front means “fill in the {boxes} with the variables”. So {name} becomes whatever the player typed.print(story) — show the finished story with all the words slotted in. Each
{word} in the template is replaced by the player’s answer.
f before the quotes — then {name} prints literally instead of the player's word.f right before the opening quote to enable {box} filling.{} — {nmae} causes an error.{} matches the variable exactly.""" for text that spans several lines.4 Test & Prove Each Part
The story is just text-filling, so we test that the player’s words actually end up in the finished story.
def make_story(name, place, verb, adjective):
"""Build the Mad Libs story from the given words."""
return (f"One day, {name} decided to visit {place}. "
f"On the way, they could not stop {verb}! "
f"Everyone agreed it was the most {adjective} day ever.")
def test_name_in_story():
"""The name appears in the finished story."""
story = make_story("Sam", "Paris", "laughing", "amazing")
assert "Sam" in story
def test_place_in_story():
"""The place appears in the finished story."""
story = make_story("Sam", "Paris", "laughing", "amazing")
assert "Paris" in story
def test_all_words_present():
"""Every word the player gave appears in the result."""
story = make_story("Sam", "Paris", "laughing", "amazing")
for word in ("Sam", "Paris", "laughing", "amazing"):
assert word in story
Run with pytest -v. We moved the story-building into a make_story function so tests can check the words land in the text — without needing a human to type them.
5 The Interface
What it expects
Enter a name: Sam
Enter a place: the moon
Enter a verb: dancing
Enter an adjective: sparklyWhat it returns
One day, Sam decided to visit the moon.
On the way, they could not stop dancing!
Everyone agreed it was the most sparkly day ever.6 Run It & Automate It
python3 madlibs.pyAnswer each prompt and read your silly story.
Jenkins runs the tests automatically — each line explained below.
Enter a name: Sam
Enter a place: the moon
Enter a verb (an action): dancing
Enter an adjective (a describing word): sparkly
One day, Sam decided to visit the moon.
On the way, they could not stop dancing!
Everyone agreed it was the most sparkly day ever.NameError: name ... is not defined.{} does not match any variable. Check the spelling.{name}.f before the opening quote.// Jenkinsfile — automated tests on every change.
pipeline {
agent any
stages {
stage('Get the code') { steps { checkout scm } } // download the code
stage('Install') { steps { sh 'python3 -m venv venv && . venv/bin/activate && pip install pytest' } } // test tool
stage('Test') { steps { sh '. venv/bin/activate && pytest -v' } } // run every test
}
post {
success { echo 'All tests passed.' }
failure { echo 'A test failed — look above.' }
}
}
- Longer story. Add more blanks and a second paragraph. (Teaches: more variables.)
- Pick a random story. Have two templates and choose one at random. (Teaches:
random.choice.) - Count the words. Tell the player how many words their story has. (Teaches:
lenandsplit.)