Pytest
We can install pytest and requests inside our Python virtual environment using
uv pip install requests pytestWe’ll then want to create a new folder called “tests”
and inside that, create a new file called ‘test_pytest.py’
:::[File names] Pytest looks for files with names that either start with test_ or end with _test, so it’s important that this file is named correctly :::
https://fastapi.tiangolo.com/tutorial/testing/
Writing a simple test
Section titled Writing a simple testOnce you’ve created a test file, you can begin writing tests. Say you have a function in your main file called multiplyfour, that takes an input of a number, and returns it multiplied by 4.
We would test that it’s actually multiplying by four like this:
def test_multiply(): assert multiplyfour(4) == 16When our tests are run, we’ll be told how many have passed and how many have failed, and be given specific information on the tests which failed.
Running the tests
Section titled Running the testsTo run your tests, you can simply run
pytestin the terminal.
Testing your SQL Database
Section titled Testing your SQL DatabaseTesting our SQL database using Pytest is thankfully nice and easy using fastapi and pytest.
First, we’ll want to add some more imports to our test file
naming
We use “main” here because that’s what our main python file is called, if yours is called something else, you’ll have to use that name.
from fastapi.testclient import TestClientfrom sqlmodel import Session, SQLModel, create_engineimport pytestfrom main import app, get_sessionThen, we’ll create a fixture function. This will ensure that all of our tests are using an entirely fresh database, and that the database data doesn’t persist between tests, which could cause problems for certain tests.
@pytest.fixture()def test_db(): SQLModel.metadata.create_all(engine) yield SQLModel.metadata.drop_all(engine)This function will ensure that whenever we pass it as a reference to a test, that test starts with an empty db, and that the db is cleared afterward, even if the test fails.
Then, let’s create a new function to see if a post is added to the database correctly.
First we create a new testing function and then a testclient, based on our app.
def test_create_post(): client = testClient(app)Then, we use that testclient to invoke the function where we create a new post and pass it through some test parameters.
response = client.post( "/posts/", params = {"post_title": "test", "post_content": "test", "post_date": "test"} )Then, we extra the returned data (In this case, it should be a post) and check if the data matches what we’d expect using assert
data = response.json()assert data["title"] == "test"assert data["content"] == "test"assert data["data_posted"] == "test"assert data["id"] is not Nonefor a full test function that looks like this:
def test_create_post(): client = TestClient(app)
response = client.post( "/posts/", params = {"post_title": "test", "post_content": "test", "post_date": "test"} )
data = response.json() assert data["title"] == "test" assert data["content"] == "test" assert data["data_posted"] == "test" assert data["id"] is not NoneLet’s also create a test that checks to see if posts are read from the database correctly. We’ll add two dummy posts the same way we did in the previous test, and then run our get function, and then check the length.
Adding the posts to the database is easy, as we’ve just done that.
def test_read_posts(test_db): client = TestClient(app)
client.post( "/posts/", params = {"post_title": "test", "post_content": "test", "post_date": "test"} )
client.post( "/posts/", params = {"post_title": "test2", "post_content": "test2", "post_date": "test2"} )Then, let’s run that get function and store the return value as response
response = client.get( "/posts/" )
data = response.json()and then check the length
assert len(data) == 2For a test function that looks like this:
def test_read_posts(test_db): client = TestClient(app)
client.post( "/posts/", params = {"post_title": "test", "post_content": "test", "post_date": "test"} )
client.post( "/posts/", params = {"post_title": "test2", "post_content": "test2", "post_date": "test2"} )
response = client.get( "/posts/" )
data = response.json() assert len(data) == 2