avatarTravis Luong

Summary

This article provides a guide on testing an API using Pytest and Requests within a Full Stack Application built with Next.js, FastAPI, and PostgreSQL.

Abstract

The article titled "How to Test an API with Pytest and Requests" serves as a continuation to previous tutorials on building a Full Stack Application with Next.js, FastAPI, and PostgreSQL. It outlines the process of setting up a testing environment, including creating a directory, setting up a virtual environment, and installing necessary packages like Pytest, Requests, and Python-dotenv. It details the creation of configuration files, environment files, and test scripts for both notes and user functionalities. The tests cover both public and private endpoints, ensuring the API behaves as expected. The tutorial emphasizes the importance of automated testing for consistent API functionality and workflow verification, which enhances developer confidence during codebase changes.

Opinions

  • Automated API testing is crucial for efficient development, replacing manual testing with code.
  • Testing is beneficial for verifying API functionality and maintaining expected behavior after changes.
  • The use of Pytest and Requests is recommended for writing API tests.
  • The tutorial advocates for the creation of a .env.example and .env files for environment variable management.
  • Global variables for username, password, and token are used in user-related tests to maintain state across different test functions.
  • The article suggests that even light integration tests contribute significantly to developer confidence.
  • It is implied that the reader has prior knowledge of building a Full Stack Application with Next.js, FastAPI, and PostgreSQL, as covered in previous tutorials.

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

  1. Full Stack Next.js, FastAPI, PostgreSQL Tutorial
  2. How to Build a Full Stack Next.js, FastAPI, PostgreSQL Boilerplate Tutorial
  3. How to Deploy Next.js, FastAPI, and PostgreSQL with Shell Scripts
  4. How to Develop a Full Stack Next.js, FastAPI, PostgreSQL App Using Docker
  5. How to Build a User Authentication Flow with Next.js, FastAPI, and PostgreSQL
  6. 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-test

Create virtualenv.

$ python -m venv venv
$ . venv/bin/activate

Install pytest and requests.

$ pip install pytest requests python-dotenv

Create a .env.example.

API_URL=http://localhost:8000

Create a .env.

API_URL=http://localhost:8000

Create a .gitignore.

__pycache__
venv
.pytest_cache
.env

Create a config.py.

import os
from dotenv import load_dotenv
load_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 == 200
def test_post_note():
    payload = {"text": "hello world", "completed": False}
    r = requests.post(f'{config.API_URL}/notes/', json=payload)
    assert r.status_code == 200

Create a test_users.py.

import requests
import string
import random
from config import config
username = None
password = None
token = None
def 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 == 200
def 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 == 200
def 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 == 200
def 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 == 200

Run the tests.

$ pytest

Run the tests with stdout for all tests.

$ pytest -rA

Conclusion

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.

Fastapi
Python
Web Development
Testing
Automation
Recommended from ReadMedium