How to Test an API with Pytest and Requests
In previous tutorials, we learned how to build a Full Stack Application with Next.js, FastAPI, and PostgreSQL. In this tutorial, we will learn how to test it with Pytest and Requests.
Table of Contents
- Full Stack Next.js, FastAPI, PostgreSQL Tutorial
- How to Build a Full Stack Next.js, FastAPI, PostgreSQL Boilerplate Tutorial
- How to Deploy Next.js, FastAPI, and PostgreSQL with Shell Scripts
- How to Develop a Full Stack Next.js, FastAPI, PostgreSQL App Using Docker
- How to Build a User Authentication Flow with Next.js, FastAPI, and PostgreSQL
- How to Test an API with Pytest and Requests
Writing tests for backend APIs has major benefits. One, they can be used while developing, so instead of manually using a GUI HTTP client to test your API, you can automate it with code. This is helpful when you find yourself repeatedly running a series of requests to test a specific workflow such as user sign up and log in. Second, they can be used to verify the functionality of your API and make sure it is working as expected.
Create nfp-test directory.
$ mkdir nfp-testCreate virtualenv.
$ python -m venv venv
$ . venv/bin/activateInstall pytest and requests.
$ pip install pytest requests python-dotenvCreate a .env.example.
API_URL=http://localhost:8000Create a .env.
API_URL=http://localhost:8000Create a .gitignore.
__pycache__
venv
.pytest_cache
.envCreate a config.py.
import os
from dotenv import load_dotenvload_dotenv()class Config:
API_URL = os.getenv("API_URL")config = Config()Create a test_notes.py.
import requests
from config import config
def test_get_notes():
r = requests.get(f'{config.API_URL}/notes/')
assert r.status_code == 200def test_post_note():
payload = {"text": "hello world", "completed": False}
r = requests.post(f'{config.API_URL}/notes/', json=payload)
assert r.status_code == 200Create a test_users.py.
import requests
import string
import random
from config import configusername = None
password = None
token = Nonedef test_post_users():
global username
global password
username = ''.join(random.sample(string.ascii_letters, 8))
password = ''.join(random.sample(string.ascii_letters, 8))
payload = {
"username": username,
"password": password
}
r = requests.post(f'{config.API_URL}/users/', json=payload)
assert r.status_code == 200def test_post_token():
global token
payload = {"username": username, "password": password}
r = requests.post(f'{config.API_URL}/token', data=payload)
json = r.json()
token = json['access_token']
assert r.status_code == 200def test_get_users_me():
headers = {'Authorization': f'Bearer {token}'}
r = requests.get(f'{config.API_URL}/users/me/', headers=headers)
json = r.json()
assert json['username'] == username
assert r.status_code == 200def test_get_users_me_items():
headers = {'Authorization': f'Bearer {token}'}
r = requests.get(f'{config.API_URL}/users/me/items/', headers=headers)
assert r.status_code == 200Run the tests.
$ pytestRun the tests with stdout for all tests.
$ pytest -rAConclusion
Congratulations, you have written the first API tests for our NFP boilerplate app. You have used pytest and requests to test the public endpoints as well as the private endpoints. Even light integration tests such as the ones above will go a long way in increasing developer confidence when making changes to a codebase.
Originally published at https://www.travisluong.com on December 24, 2021.
