Testing FastAPI endpoints using fastapi.testclient

This post shows you an example of how to use fastapi.testclient provided by FastAPI. This testclient will help anyone to write code level tests quickly.


Background

Recently, we have developed an internal application using FastAPI. I thought to document a quick testing approach which may help software engineers to write test cases quickly. Here I have used fastapi.testclient instead of the requests module as I wanted to explore it.


The application under test

Our application under test is developed using FastAPI and exposes certain API endpoints which will be used to send skype messages to the predefined channels. I will be taking only one sample method the purpose of this blog.

CULTURE_FILE = 'blah blah blah'
 
def get_messages_from_file(filename):
    "Return a list of culture related messages"
    lines = []
    with open(filename, 'r') as fp:
        lines = fp.readlines()
 
    return lines
 
@app.get("/message")
def get_message():
    "Return a random message"
    lines = get_messages_from_file(CULTURE_FILE)
    message = random.choice(lines)
 
    return {'msg':message.strip()}

Let us assume this code exists in a file called main.py.


Using fastapi.testclient

The testclient is a wrapper written using the requests module in Python, You will need to install the requests module to use test client. Our way of writing this test will involve the following steps:

1. Create a Test client.
2. Get the response from the client using the exposed endpoint.
3. Assert the status code for the response as 200.
4. Assert the response for non-empty messages.
5. Assert the response for the correct message taken from the file.


1. Create Test client

Create a new file called test_main.py and add the following lines:

"""
Test for the main page using fastapi.testclient.
"""
import os
import sys
from fastapi.testclient import TestClient
import main
from main import app
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
# Declaring test client
client = TestClient(app)

At this stage, we have imported the necessary modules and created test client. Note that we have imported appfrom the main and parsing that while creating test client.


2. Get the response from the client using the exposed endpoint

Now, within the test_get_message() method, create a response using exposed endpoint

# Test for status code for get message
def test_get_message():
    "asserting status code"
    response = client.get("/message")

3. Assert the status code for the response as 200

You can assert the response is showing status code as 200

assert response.status_code == 200

4. Assert the response for non-empty messages

This step will ensure that we don’t get an empty message before validating the actual message from the file. We will create new method test_get_message_text().

# Test for asserting random message is in the file
def test_get_message_text():
    "asserting random message is in the file"
    response = client.get("/message")
    message = response.json()
    assert message['msg'] != ''

5. Assert the response for the correct message taken from the file

We will now check that message we got is really from the intended file. In this case CULTURE_FILE

# Test for asserting random message is in the file
def test_get_message_text():
    "asserting random message is in the file"
    response = client.get("/message")
    message = response.json()
    assert message['msg'] != ''
    with open(main.CULTURE_FILE, 'r') as file_handler:
        lines = [line.strip() for line in file_handler]
    assert message['msg'] in lines

Putting it all together

Here is how our test looks:

"""
Test for the main page using fastapi.testclient.
"""
import os
import sys
from fastapi.testclient import TestClient
import main
from main import app
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 
# Declaring test client
client = TestClient(app)
 
# Test for status code for get message
def test_get_message():
    "asserting status code"
    response = client.get("/message")
    assert response.status_code == 200
 
# Test for asserting random message is in the file
def test_get_message_text():
    "asserting random message is in the file"
    response = client.get("/message")
    message = response.json()
    assert response.json()["msg"] != ''
    with open(main.CULTURE_FILE, 'r') as file_handler:
        lines = [line.strip() for line in file_handler]
    assert message['msg'] in lines

If you are working on testing applications using FastAPI, do consider using fastapi.testclient for your tests. I hope this article would help you to build quick tests around test client.


I have around 14 years of experience in Software Testing. During my testing career, I worked on ETL Testing, Big Data Testing, Security Testing, Performance Testing as well as Automation Testing. I have domain experience in Investment banking, PLM (Product Life Cycle Management), GRC (Governance Risk Compliance), Sales, and Marketing. During my testing career, I decided to join Qxf2 because of the emphasis given to R&D and learning new technologies to solve testing world problems. On a personal front, I enjoy reading books during my leisure time.

Be First to Comment

Leave a Reply

Your email address will not be published.