Open this lesson in your favourite AI. It'll walk you through the why, explain the demo, and quiz you on the try-it list.
A smoke test is the minimum set of checks that verifies a new build is worth testing further. If the login page 404s, there's no point running 500 regression tests. Smoke tests are fast (under 10 minutes), target the critical happy paths (can you log in, can you reach the main feature, does the API respond), and run automatically after every deployment. The metaphor comes from electronics: when you power on a new circuit board for the first time, if it smokes, you don't debug — you start over. In software: if smoke tests fail, the build is rejected before any more testing time is wasted. Well-designed smoke tests are the difference between finding a broken deploy in 10 minutes vs 4 hours.
Smoke tests define the minimum viable confidence threshold after a deploy — if the critical happy paths fail, running 500 regression tests is wasted effort and the build should be rejected immediately. A well-structured suite exits with code 1 on failure so CI pipelines can block deployment automatically. Keeping smoke tests under 10 minutes is not a nicety; it's what makes the gate economically viable at 5+ deploys per day.
import requests, sys, time
BASE = "https://jsonplaceholder.typicode.com" # replace with your app URL
SMOKE_TESTS = [
# (description, method, path, expected_status, optional_body_check)
("Homepage loads", "GET", "/posts", 200, None),
("User endpoint reachable", "GET", "/users/1", 200, lambda r: "email" in r.json()),
("API returns JSON", "GET", "/posts/1", 200, lambda r: r.headers.get("Content-Type","").startswith("application/json")),
("404 for missing resource", "GET", "/posts/99999", 404, None),
("POST creates resource", "POST", "/posts", 201, lambda r: "id" in r.json()),
]
passed, failed = 0, 0
print(f"Running {len(SMOKE_TESTS)} smoke tests against {BASE}\n")
for desc, method, path, expected_status, body_check in SMOKE_TESTS:
try:
t0 = time.perf_counter()
resp = requests.request(method, BASE + path,
json={"title":"smoke","body":"test","userId":1} if method=="POST" else None,
timeout=5)
ms = round((time.perf_counter() - t0) * 1000)
status_ok = resp.status_code == expected_status
body_ok = body_check(resp) if body_check else True
if status_ok and body_ok:
print(f" ✓ [{ms:4d}ms] {desc}")
passed += 1
else:
reason = f"status={resp.status_code}" if not status_ok else "body check failed"
print(f" ✗ [{ms:4d}ms] {desc} ← {reason}")
failed += 1
except requests.Timeout:
print(f" ✗ [timeout] {desc}")
failed += 1
print(f"\nResult: {passed}/{passed+failed} passed")
sys.exit(0 if failed == 0 else 1) # non-zero exit fails CI pipelinepython3 main.pyms variable already calculated. This is a performance smoke test — not a full load test, just a basic sanity check that the server isn't unusually slow.sys.exit(1) paths so the script exits with code 1 on failure (already in the demo). Now wire it into a shell script: python smoke.py && echo 'Smoke passed — proceed to regression'. This is how smoke gates work in CI.'title' in resp.json(). This goes beyond just 'did I get a 200' to 'did I get meaningful content'. This catches cases where a 200 OK returns an empty page or error page.Use these three in order. Each builds on the one before.
In one paragraph, explain the difference between a smoke test and a regression test suite. What makes smoke tests fast, and why is that important for CI/CD pipelines?
Walk me through how a smoke test integrates into a deployment pipeline: when exactly does it run, what happens when it fails (who is notified, does the deploy roll back), and what's the maximum acceptable execution time before it slows down deploy frequency?
My team deploys 5 times per day. We have 400 regression tests that take 45 minutes to run. Design a testing strategy that maximizes deploy frequency while minimizing risk: which tests run on every deploy (smoke), which run on every PR (regression subset), which run nightly (full suite), and how you'd decide which tests belong in which tier.