Git Checkpoints and Testing Before You Trust a Script

Save points and practice runs for code that touches real files

Intermediate 11 min

In this lesson

Once a script starts changing real files, two habits protect you: Git gives your project save points you can return to, and tests are little practice runs that confirm the important pieces still work. This lesson keeps both practical — just enough Git workflow and just enough testing to make automation trustworthy.

Explain it like I’m 5

Git is the save-point system for your code; tests are quick practice runs that check the risky parts before you let them loose on real files.

Git: save points for your project

Git records snapshots of your project called commits. Each small, well-described commit is a save point you can return to if a change goes wrong — which matters most when a script is rewriting real files. You don’t need full Git training here, just the everyday loop.

Example
git init                                 # start tracking this project
git add file_tool.py                     # stage your changes
git commit -m "Add safe dry-run mode"    # save a checkpoint
git log --oneline                        # see your save points
A tiny Git workflow — small, described commits act as save points.

Tests: practice runs for your helpers

A test checks that a piece of code does what you expect. The cheapest test is an assert: a statement that must be true, or Python raises an AssertionError. Test the pure helper functions — the ones that just compute a result — so you can verify your logic without ever touching real files.

Example
def clean_filename(name):
    return name.strip().lower().replace(" ", "_")

# A few quick checks before trusting it on real files:
assert clean_filename("  My File.TXT ") == "my_file.txt"
assert clean_filename("Report 2024") == "report_2024"
print("All checks passed")
Output
All checks passed
If any assert were false, you'd see an error instead.

Write a test, then trust the helper

Reading a failing test is a skill: the message tells you what was expected versus what happened. Practise by working out the expected result by hand and asserting it.

Here's a helper that turns a title into a URL slug. Add two assert checks with the correct expected results, then keep the success line.

def slugify(title):
    return title.strip().lower().replace(" ", "-")

# TODO: assert slugify("Hello World") == ?
# TODO: assert slugify("  Spaced Out  ") == ?
print("All checks passed")

Common mistake: Making one giant commit after many unrelated changes

Why it happens:

It feels efficient to code for an hour and commit once at the end.

How to fix it:

Commit in small, focused steps with clear messages. Each becomes a clean save point you can roll back to without losing unrelated work.

Common mistake: Testing only the happy path

Why it happens:

The obvious case is easiest to check, so the odd inputs — empty strings, missing extensions — get skipped.

How to fix it:

Add a test for the edge cases too. Bugs usually hide in the inputs you didn’t think to try.

Common mistake: Running tests against real, important folders

Why it happens:

It’s convenient to point a test at the actual files the script will process.

How to fix it:

Test pure helper functions, or use a small folder of throwaway sample data. Never let a test mutate data you can’t afford to lose.

Why prefer small, frequent commits?

What does an assert statement check?

Why test pure helper functions separately from file-moving code?

Mini exercise (medium)

Write a helper safe_name(name) that trims a filename, lowercases it, and replaces spaces with underscores — for example " My Report " becomes "my_report". Then it should pass tests on at least two inputs.

Do it here. Finish the code below and press Run to try your answer right in the browser — no setup needed.

def safe_name(name):
    # TODO: trim, lowercase, and replace spaces with underscores
    return name

# TODO: add two asserts that prove it works
print("done")

What to learn next

You saw how small, described Git commits act as save points, and how a quick assert test confirms a pure helper works before it ever touches real files — with a first look at pytest for scaling tests up. You wrote and tested a safe_name() helper.

The last piece of a trustworthy project is making it run the same anywhere. Virtual Environments, requirements.txt, and Reproducibility shows how to isolate and pin your dependencies. When you’re ready, continue to the next lesson.