PythonFastAPIPyTestTestCase

    How to Add Test Cases in FastAPI (and Why They Matter)

    FastAPI makes it easy to build APIs quickly, but writing the API is only one part of a good backend project. A real project also needs tests. Test cases help us confirm that our en...

    Apr 30, 2026
    6 min read
    168 views
    How to Add Test Cases in FastAPI (and Why They Matter)

    FastAPI makes it easy to build APIs quickly, but writing the API is only one part of a good backend project. A real project also needs tests. Test cases help us confirm that our endpoints work as expected, keep bugs from coming back, and give us confidence when we change code later.

    In this blog, we will look at:

    • why we use test cases in FastAPI
    • what is necessary before writing tests
    • how to organize tests in a separate tests folder
    • how to write a simple CRUD test

    Why We Use Test Cases in FastAPI

    When we build an API, many things can go wrong:

    • an endpoint may return the wrong status code
    • validation may stop working
    • database changes may break old behavior
    • one feature fix may accidentally break another feature

    Test cases protect us from these problems.

    Main benefits of testing

    1. It checks that the API behaves correctly

    If POST /products/ should create a product and return 201, a test confirms that behavior every time.

    2. It prevents regressions

    A regression means something that worked before stops working after a new code change. Tests catch this early.

    3. It makes refactoring safer

    If you want to improve folder structure, service logic, or database code, tests tell you if the external behavior is still correct.

    4. It documents expected behavior

    A good test file shows how the API is supposed to work. It becomes a living example for the team.

    5. It saves debugging time

    Finding a bug after deployment is expensive. Finding it with pytest during development is much easier.

    What Is Necessary Before Writing FastAPI Tests

    Before writing tests, we usually need a few things:

    1. pytest

    pytest is the most common testing framework in Python. It helps us write simple and readable tests.

    2. TestClient

    FastAPI provides TestClient so we can call API routes like a real client without starting the server manually.

    python
    from fastapi.testclient import TestClient

    3. A separate test database

    We should not run tests on the main development database. Tests may create, update, and delete data. A separate SQLite test database is a common and safe choice.

    4. Dependency override

    If the app normally uses the real database connection, tests should override that dependency and use the test database instead.

    5. A separate tests folder

    Keeping tests inside a dedicated tests folder makes the project cleaner and easier to maintain.

    A common structure looks like this:

    text
    app/
    tests/
      conftest.py
      test_product_crud.py

    How to Add Test Cases in FastAPI

    Let us look at the basic setup.

    Step 1: Install pytest

    Add pytest to your project dependencies.

    toml
    dependencies = [
        "fastapi[standard]>=0.136.1",
        "sqlalchemy>=2.0.49",
        "pytest>=8.4.2",
    ]

    Step 2: Create a tests folder

    Inside the root of the project, create a separate folder:

    text
    tests/

    This keeps test files away from application logic and makes the project easier to navigate.

    Step 3: Create conftest.py

    conftest.py is useful for shared fixtures. In FastAPI, we often use it to:

    • create a test database
    • override the database dependency
    • return a reusable client

    Example:

    python
    import sys
    from pathlib import Path
    from collections.abc import Generator
    
    import pytest
    from fastapi.testclient import TestClient
    from sqlalchemy import create_engine
    from sqlalchemy.orm import Session, sessionmaker
    
    sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
    
    from app.core.database import get_db
    from app.main import app
    from app.models.product import Base
    
    TEST_DATABASE_URL = "sqlite:///./test_products.db"
    
    engine = create_engine(
        TEST_DATABASE_URL,
        connect_args={"check_same_thread": False},
    )
    TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
    
    
    def override_get_db() -> Generator[Session, None, None]:
        db = TestingSessionLocal()
        try:
            yield db
        finally:
            db.close()
    
    
    @pytest.fixture()
    def client() -> Generator[TestClient, None, None]:
        Base.metadata.drop_all(bind=engine)
        Base.metadata.create_all(bind=engine)
        app.dependency_overrides[get_db] = override_get_db
    
        with TestClient(app) as test_client:
            yield test_client
    
        app.dependency_overrides.clear()

    This fixture gives each test a clean API client and isolates database usage.

    Step 4: Write a test file

    Now create a separate file like tests/test_product_crud.py.

    Example:

    python
    from fastapi.testclient import TestClient
    
    
    def test_product_crud_flow(client: TestClient) -> None:
        create_response = client.post(
            "/products/",
            json={
                "name": "Monitor",
                "description": "4K display",
                "price": "399.99",
                "quantity": 10,
            },
        )
    
        assert create_response.status_code == 201
        created_product = create_response.json()
        product_id = created_product["id"]
    
        get_response = client.get(f"/products/{product_id}")
        assert get_response.status_code == 200
    
        update_response = client.put(
            f"/products/{product_id}",
            json={
                "name": "Monitor Pro",
                "description": "4K display",
                "price": "449.99",
                "quantity": 8,
            },
        )
        assert update_response.status_code == 200
    
        delete_response = client.delete(f"/products/{product_id}")
        assert delete_response.status_code == 204

    This single test checks the main CRUD flow:

    • create product
    • read product
    • update product
    • delete product

    Step 5: Run the tests

    Use pytest to run the separate test folder:

    bash
    pytest tests

    Or, in this project setup:

    bash
    uv run pytest tests

    What Should We Test in FastAPI?

    When writing tests, do not only test the happy path. A better API test strategy includes:

    1. Success cases

    Example:

    • product is created successfully
    • product list returns 200
    • delete returns 204

    2. Error cases

    Example:

    • product not found returns 404
    • invalid request body returns 422
    • negative quantity is rejected

    3. Validation rules

    Example:

    • empty name should fail
    • price must be greater than zero

    4. Database behavior

    Example:

    • update really changes saved data
    • delete removes the record

    Why a Separate Test Folder Is a Good Idea

    Using a separate tests folder is not required by FastAPI, but it is a strong best practice.

    Benefits of a separate folder

    • keeps application code clean
    • makes tests easy to find
    • supports shared fixtures with conftest.py
    • works well with pytest
    • helps the project scale as more features are added

    If your project grows to users, orders, auth, and products, the tests folder becomes even more valuable.

    Best Practices for FastAPI Testing

    • keep tests small and readable
    • use a test database instead of the real database
    • reset test data between tests
    • test both success and failure cases
    • keep shared setup in conftest.py
    • name test files clearly, such as test_product_crud.py

    Conclusion

    Test cases are necessary in FastAPI because they improve reliability, reduce bugs, and make future changes safer. They are not just for large companies or complex projects. Even a small CRUD API becomes much easier to maintain when it has a good test setup.

    The most important things you need are:

    • pytest
    • TestClient
    • a separate test database
    • dependency override
    • a dedicated tests folder

    With these pieces in place, you can confidently test your FastAPI application and grow the project without fear of breaking existing features.

    J
    Written by

    Jobi S S

    Portfolio

    admin

    Sharing technical insights, engineering concepts, and practical modern software development guides.

    Community Discussion

    Enjoyed this read? Show your support or share your thoughts.

    Comments (0)

    No comments yet. Be the first to comment!

    📬 Enjoyed this article?

    Get new posts on Django, FastAPI, and system design straight to your inbox. No spam — unsubscribe whenever you want.