Skip to content

pytest for API Testing with httpx

DodaTech Updated 2026-06-28 3 min read

In this tutorial, you will learn about pytest for api testing with httpx. We cover key concepts, practical examples, and best practices to help you master this topic.

pytest with httpx provides a modern approach to testing Python APIs. httpx offers both sync and async clients, while pytest fixtures manage test setup and teardown. Together they enable fast, reliable API tests.

What You'll Learn

  • pytest setup for API testing
  • httpx sync and async clients
  • Fixtures for test data and auth
  • Parameterized tests
  • Mocking external services with respx

Why It Matters

pytest is the most popular Python test framework. httpx is the modern HTTP client with async support. Combined, they provide a powerful API testing stack for Python microservices.

Real-World Use

FastAPI uses httpx TestClient internally. Django REST framework examples use pytest. Many Python Serverless APIs use pytest for Integration Testing.

flowchart LR
    Test[pytest Test] --> Fixtures[Fixtures]
    Fixtures --> TestClient[httpx Client]
    Fixtures --> Database[Test Database]
    Fixtures --> Auth[Auth Tokens]
    TestClient --> App[FastAPI/Flask App]
    App --> Response[Response]
    TestClient --> Assert[Assertions]

Teacher Mindset

Use fixtures for shared setup (database, auth, client). Use pytest.mark.parametrize for data-driven tests. Use respx to mock external HTTP calls. Keep tests independent and idempotent.

Code Examples

# Example 1: Basic pytest with httpx
import pytest
import httpx

BASE_URL = "http://api.example.com"

def test_get_users():
    response = httpx.get(f"{BASE_URL}/api/users")
    assert response.status_code == 200
    data = response.json()
    assert isinstance(data, list)
    assert len(data) > 0
# Example 2: Async tests with fixtures
import pytest
import httpx

@pytest.fixture
async def client():
    async with httpx.AsyncClient(base_url="http://test") as client:
        yield client

@pytest.fixture
async def auth_token(client):
    response = await client.post("/auth/login", json={
        "username": "admin",
        "password": "secret"
    })
    return response.json()["token"]

@pytest.mark.asyncio
async def test_create_user(client, auth_token):
    response = await client.post(
        "/api/users",
        json={"name": "Alice", "email": "alice@test.com"},
        headers={"Authorization": f"Bearer {auth_token}"}
    )
    assert response.status_code == 201
    data = response.json()
    assert data["name"] == "Alice"
    assert "id" in data
# Example 3: Parameterized tests with error cases
import pytest

create_user_data = [
    ({"name": "Alice", "email": "alice@test.com"}, 201),
    ({"name": ""}, 422),  # Missing email
    ({"email": "invalid"}, 422),  # Invalid email
    ({}, 422),  # Empty body
]

@pytest.mark.parametrize("payload,expected_status", create_user_data)
@pytest.mark.asyncio
async def test_create_user_validation(client, auth_token, payload, expected_status):
    response = await client.post(
        "/api/users",
        json=payload,
        headers={"Authorization": f"Bearer {auth_token}"}
    )
    assert response.status_code == expected_status

Common Mistakes

  • Using one client instance for all tests without isolation
  • Not using async fixtures for async tests
  • Mixing sync and async code without proper markers
  • Hardcoding test data instead of using factories
  • Not cleaning up test database state between tests

Practice

  1. Write a sync test for GET /api/users.
  2. Write an async test with a fixture for the HTTP client.
  3. Add a fixture that authenticates and returns a token.
  4. Use parametrize to test multiple input combinations.
  5. Challenge: Use respx to mock an external dependency in an API test.

FAQ

What is the difference between httpx and requests?

httpx supports both sync and async, HTTP/2, and has a similar API to requests. requests is sync-only and more established.

Do I need pytest-asyncio for async tests?

Yes. Install pytest-asyncio and mark async tests with @pytest.mark.asyncio.

How do I test FastAPI apps?

Use TestClient from starlette.testclient or httpx with the ASGI transport.

Can I use pytest with Flask?

Yes. Use Flask's test client or httpx to make requests against the Flask app.

How do I handle database transactions in tests?

Use pytest fixtures with transaction rollback. Each test starts a transaction and rolls it back after.

Mini Project

Write a pytest test suite for a Python REST API with: async httpx client fixture, auth token fixture, CRUD tests for a resource, parameterized validation tests, and database cleanup after tests.

What's Next

Next, you will learn about using the requests library for Python API testing.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro