Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 53

Testing Model Endpoints

Recommended resources

Welcome back! In the last lesson, you successfully built and ran a FastAPI service to wrap your machine learning model. You saw how FastAPI's automatic documentation provides a fantastic interface for manual testing. While the Swagger UI is great for quick, interactive checks, real-world development and MLOps workflows demand automation.

This lesson focuses on exactly that: moving from manual clicks to programmatic and automated testing. You will learn how to send requests to your running API endpoint using Python scripts and command-line tools. This skill is fundamental for integrating your model into larger applications, setting up monitoring, or building a continuous integration/continuous delivery (CI/CD) pipeline.

Given your experience with backend frameworks like Django and Node.js, you're already familiar with the client-server model of REST APIs. Today, you'll be on the client side, using Python to interact with the API you just built.

1. Programmatic Testing with the requests Library

While your FastAPI application is running (via uvicorn), it's listening for HTTP requests at a specific network address, typically http://127.0.0.1:8000. Any application that can send an HTTP request can interact with your model. In Python, the standard tool for this is the requests library.

The process is straightforward:

  1. Construct the URL of your API endpoint (e.g., http://127.0.0.1:8000/predict).
  2. Create a Python dictionary containing the input data for your model. This is the "payload."
  3. Use requests.post() to send the payload as JSON to the endpoint.
  4. Inspect the response object to get the status code and the prediction returned by the API.

The following video provides an excellent walkthrough of this exact process.

Build a Machine Learning API Using FastAPI & Scikit-Learn (Step-by-Step Python Tutorial)

This clip from the "Build a Machine Learning API" tutorial shows how to create a simple Python client in a Jupyter Notebook to test the API you just built.

Watch the section on programmatic testing. Pay close attention to how the URL is defined, how the payload dictionary is structured, and how requests.post() is called with the json argument. Notice the difference between viewing the raw response object versus the parsed JSON content with response.json().

Let's break down the key Python code for sending a request. Assuming your API expects size_square_feet and bedrooms, a test script would look like this:

import requests

# The URL of your running FastAPI application's prediction endpoint
url = "http://127.0.0.1:8000/predict"

# The input data for your model, as a Python dictionary
# This must match the Pydantic model you defined in FastAPI
payload = {
    "size_square_feet": 1500.0,
    "bedrooms": 3
}

# Send the POST request
# The `json` parameter automatically serializes the dict to JSON and sets the correct headers
response = requests.post(url, json=payload)

# Check the response
if response.status_code == 200:
    # If successful, print the prediction
    prediction_data = response.json()
    print(f"API Response: {prediction_data}")
    print(f"Predicted Price: {prediction_data['predicted_price']}")
else:
    # If there was an error, print the status code and error message
    print(f"Error: Received status code {response.status_code}")
    print(f"Response: {response.text}")

The requests.post(url, json=payload) call is doing the heavy lifting. It converts your payload dictionary into a JSON string, sets the Content-Type HTTP header to application/json, and sends it to your API. Your FastAPI application then receives this, validates it with your Pydantic model, and processes the prediction.


Your Turn: Write a Test Script

  1. Make sure the FastAPI application you built in the last lesson is running (uvicorn main:app --reload).
  2. Create a new Python file, e.g., test_api.py.
  3. Install the requests library if you haven't already: pip install requests.
  4. In test_api.py, write a script that sends a sample data point to your /predict endpoint.
  5. Print the status code and the JSON response you get back.

2. Expanding Your Testing Toolkit

While sending single requests is useful, you'll often need to test other scenarios.

Testing Batch Predictions

What if you need to predict on 100 data points at once? Sending 100 separate HTTP requests would be inefficient. A better approach is to create a new endpoint, say /predict_batch, that accepts a list of inputs and returns a list of predictions.

The same video resource shows how to implement and test this.

Build a Machine Learning API Using FastAPI & Scikit-Learn (Step-by-Step Python Tutorial)

This section demonstrates how to extend your API to handle batch predictions and how to modify your test script accordingly.

Watch from the batch endpoint. Observe how a new Pydantic model is created to handle a list of inputs and how the test script's payload is changed to a dictionary containing a list of objects.

This is a common pattern for production ML services, as it significantly improves throughput.

Testing from the Command Line with curl

Sometimes you need to run a quick test without writing a full Python script. curl is a powerful command-line tool for transferring data with URLs, and it's perfect for this. You can make a POST request directly from your terminal.

This image shows the structure of a `curl` command for sending a POST request with a JSON payload, a common method for quick API testing from the terminal.

This image shows the structure of a curl command for sending a POST request with a JSON payload, a common method for quick API testing from the terminal.

The syntax for sending a JSON payload looks like this:

curl -X POST "http://127.0.0.1:8000/predict" \
-H "Content-Type: application/json" \
-d '{"size_square_feet": 1600, "bedrooms": 4}'
  • -X POST: Specifies the HTTP method.
  • -H "Content-Type: application/json": Sets the content type header, telling the server we are sending JSON.
  • -d '...': Specifies the data (payload) to send. Note the use of single quotes around the JSON string to prevent shell interpretation issues.

Go ahead and try running this command in your terminal while your Uvicorn server is active. You should see the JSON response printed directly to the console.


3. A Look Ahead: Automated Testing with pytest

What we've done so far is programmatic testing. The next level of maturity is automated testing, where you build a formal test suite that can be run automatically to validate your application's behavior. The standard framework for this in Python is pytest.

FastAPI is designed to be easily tested with pytest using a special TestClient.

Testing FastAPI Applications with pytest | CodeSignal Learn

This article introduces the motivation for automated testing and the setup for using pytest with FastAPI.

Read the introduction "Why Testing Matters for ML APIs" and the section "Setting Up the Testing Environment". Focus on the concept of the TestClient.

The key idea of TestClient is that it lets you make requests to your FastAPI application without needing to run a live Uvicorn server. It interacts with your app directly in memory, which is much faster and more reliable for automated test environments.

A simple test using pytest and TestClient would look like this:

# In a file named test_main.py
from fastapi.testclient import TestClient
from .main import app  # Import your FastAPI app

client = TestClient(app)

def test_prediction_endpoint():
    response = client.post(
        "/predict",
        json={"size_square_feet": 2000, "bedrooms": 4}
    )
    assert response.status_code == 200
    assert "predicted_price" in response.json()

You would then run this from your terminal with the command pytest. The framework automatically discovers and runs functions starting with test_. The assert statements check if your API behaves as expected; if not, the test fails.

While we won't implement a full pytest suite today, it's the professional standard for building robust applications and a crucial component of any production-grade MLOps pipeline.


Conclusion

You have now moved beyond manual interaction and can test your model API in a repeatable, scriptable way. This is a critical step in making your model useful to the outside world.

Key Takeaways:

  • Programmatic Testing: You can use the requests library in Python to send data to your running API and verify its responses. This is essential for integration and ad-hoc testing.
  • Payload Structure: The JSON payload you send must match the structure and data types defined in your Pydantic model.
  • Command-Line Testing: The curl utility is a fast and effective way to test endpoints directly from the terminal.
  • Automated Testing: For building robust, maintainable test suites, pytest combined with FastAPI's TestClient is the industry-standard approach.

In the next lesson, we will begin our next major portfolio piece: the end-to-end machine learning project. You'll start by defining a business problem, selecting a dataset, and choosing the right evaluation metrics—the foundational steps for any successful data science project. The API deployment and testing skills you've just honed will be waiting for you at the end of that project pipeline.