How to Run REST API Tests With pytest and requests in CI
pytest plus requests gives you real HTTP integration tests that assert on status codes and JSON bodies.
Read the base URL from an env var in a fixture, call the API with requests, and assert on the response. Emit JUnit XML with --junitxml.
Test
tests/test_api.py
import os, requests
BASE = os.environ["API_BASE_URL"]
def test_health():
r = requests.get(f"{BASE}/health", timeout=10)
assert r.status_code == 200
assert r.json()["status"] == "ok"
def test_create_user():
r = requests.post(f"{BASE}/users", json={"name": "ci"}, timeout=10)
assert r.status_code == 201
assert r.json()["id"]Workflow
.github/workflows/ci.yml
jobs:
api:
runs-on: ubuntu-latest
env:
API_BASE_URL: http://localhost:8000
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: pip install -r requirements.txt pytest requests
- run: |
uvicorn app.main:app --port 8000 &
npx wait-on http://localhost:8000/health
- run: pytest --junitxml=results/pytest.xmlGotchas
- Always set a
timeout=on requests so a hung endpoint fails fast instead of stalling the job. - Keep the base URL in
API_BASE_URLso the same suite runs against local, preview, and staging.
Related guides
How to Set the API Base URL From Environment Variables in CIDrive the API base URL from an environment variable in GitHub Actions so one test suite runs unchanged agains…
How to Start the API and Wait for It Before Testing in CIStart your API in the background and block until it is ready with wait-on before API tests run in GitHub Acti…
How to Publish an API Test JUnit Report in CIEmit a JUnit XML report from any API test runner in GitHub Actions and publish it, so passed and failed reque…