Testing in the Pipeline¶
A build that succeeds only proves the image assembles. It says nothing about whether your app actually works. This lesson adds automated tests, so every push checks the app behaves correctly, and blocks the build if it does not. ✅
What we will do (in very simple steps)¶
- Write a couple of small tests for the Snapshot API
- Add a test station to the pipeline
- Watch the pipeline run your tests on every push
Why test in the pipeline?¶
You could run tests by hand, but you would forget, or skip them when rushing. Running them in the pipeline means they happen every single time, automatically, before anything ships. A broken app turns the pipeline red the moment it is pushed, so problems are caught in minutes, not in production.
Step 1: Write the tests¶
In your snapshot-app folder, create a file called test_app.py:
from app import app
def test_home_returns_ok():
client = app.test_client()
response = client.get("/")
assert response.status_code == 200
def test_home_returns_message():
client = app.test_client()
response = client.get("/")
assert response.get_json() == {"message": "Hello from Snapshot!"}
These use Flask's built-in test client, which calls your app without needing a running server. The first test checks the home route responds successfully. The second checks it returns the exact message you expect.
pytest automatically finds any file named test_*.py and runs every function starting with test_.
Step 2: Add a test station to the pipeline¶
Open .github/workflows/ci.yml and replace its contents with this:
name: CI
on: push
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- name: Check out the code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dependencies
run: pip install -r requirements.txt pytest
- name: Run tests
run: pytest
- name: Build the image
run: docker build -t snapshot-app .
Notice the order: the tests run before the build. Steps run top to bottom, and if any step fails, the rest are skipped. So a failing test stops the build from happening at all. Tests now guard the gate.
Step 3: Push and watch¶
In the Actions tab, open the run and expand the Run tests step. You will see pytest report 2 passed. The belt now tests, then builds. 🎉
✅ Checkpoint¶
You are ready for the next lesson if:
- You have a
test_app.pyfile with two tests - The pipeline runs
pytestbefore the build - The Actions log shows
2 passed
🩹 Common hiccups¶
- "No module named app": pytest runs from the repository root, where
app.pylives. Make suretest_app.pyis in the same folder asapp.py. - "pytest: command not found": the install step must include
pytest. Check theInstall dependenciesline. - Tests fail unexpectedly: read the pytest output. It shows exactly which assertion failed and what it expected versus what it got.
Next up: Reading a Red Build, where you break a test on purpose and learn to read a failing pipeline calmly.