Testing with Pytest#
Testing is an essential part of developing any kind of application, it helps ensure that our code is performing as expected. Pytest is a tool that helps expedite the testing process. Pytest has a neat functionality of identifying any files that follow the format of test_*.py
or *_test.py
in the current directory and its subdirectories.
Specifically, let’s focus on the /tests
folder. Pytest will automatically run tests on the test_app.py
file under the /tests
folder. To see Pytest in action, navigate to mini-projects/movie-rec-system
and run the following command:
pytest
Let’s take a closer look at test_app.py
to understand exactly what we’re testing in this project.
Testing the FastAPI Application#
We begin with importing the necessary dependencies.
from fastapi.testclient import TestClient
from movie_rec_system.app.app import app
client = TestClient(app)
We import the app
we’ve made from the previous section under the app.py
file. Then, we initialize the TestClient
object by passing in our FastAPI app. What the TestClient
object does is simulate HTTP requests to the FastAPI application, allowing us to test its responses and behavior. You can find more details about this in the TestClient documentation.
Let’s now break down each of our tests.
Test Root Endpoint#
We begin with just testing if the root endpoint is accessible and returns the expected message.
def test_root_endpoint():
response = client.get("/")
assert response.status_code == 200
assert response.json() == {
"message": "Welcome! You can use this API to get movie recommendations based on viewers' votes. Visit /docs for more information and to try it out!" # noqa E501
}
In this test, we use the client.get(“/”) to simulate a GET request to the root endpoint and then make assertions to check if the status code is 200
and the message returned is as expected.
Test Recommendation Endpoint#
Then we test if our endpoint can handle movie recommendations.
def test_recommendation_endpoint():
test_data = {"movie": "Inception", "num_rec": 5}
response = client.post("/recommendations/", json=test_data)
assert response.status_code == 200
response_data = response.json()
assert response_data["movie"] == "inception"
Here, we send a POST
request with the movie
and num_rec
as part of the request payload. We then assert that the returned status code is 200
and that the movie name in the response data matches the movie name we sent.
Test for Nonexistent Movie#
As for edge cases, let’s test what happens when a nonexistent movie is provided:
def test_recommendation_for_nonexistent_movie():
test_data = {"movie": "NonExistentMovie", "num_rec": 5}
response = client.post("/recommendations/", json=test_data)
assert response.status_code == 404
In this test, we are ensuring that our API correctly handles the situation where a user requests a movie that doesn’t exist. We expect a 404
status code for this case.
Test Recommendation Result#
Finally, let’s have just one final test that validates the structure and the types of the fields in the response:
def test_recommendation_result():
test_data = {"movie": "Inception", "num_rec": 5}
response = client.post("/recommendations/", json=test_data)
assert response.status_code == 200
response_data = response.json()
assert isinstance(response_data["movie"], str)
assert isinstance(response_data["recommendations"], list)
assert len(response_data["recommendations"]) == test_data["num_rec"]
assert isinstance(response_data["metrics"], dict)
metrics = response_data["metrics"]
assert "popularity" in metrics
assert "vote_avg" in metrics
assert "vote_count" in metrics
assert isinstance(metrics["popularity"], float)
assert isinstance(metrics["vote_avg"], float)
assert isinstance(metrics["vote_count"], float)
This comprehensive test ensures that the movie name is a string, that recommendations are returned as a list of the expected size, and that various metrics (like popularity, average votes, and vote counts) are included in the response and have the correct types.
And there you have it! We now have a set of tests that can validate various aspects of your FastAPI application.
Happy testing!