Test & Document API0%

Test & Document API

Beginner12 min read•Updated: Jul 11, 2026
Study MaterialsCheatsheet

DRF Capstone: Automated Test Suite and Production Swagger Docs

To complete our capstone E-Commerce REST API, we implement comprehensive automated test coverage for the entire checkout flow and configure production-grade OpenAPI documentation.


1. Full E-Commerce Test Suite

Create store/tests/test_ecommerce_flow.py:

Python
from rest_framework.test import APITestCase
from rest_framework import status
from django.contrib.auth import get_user_model
from store.models import Category, Product, Cart, CartItem, Order
 
User = get_user_model()
 
class ECommerceAPITests(APITestCase):
def setUp(self):
self.user = User.objects.create_user(username='john_doe', password='secretpassword123')
self.category = Category.objects.create(name='Hardware', slug='hardware')
self.product = Product.objects.create(
category=self.category,
title='4K Ultra HD Monitor',
slug='4k-ultra-hd-monitor',
description='Crisp 3840x2160 IPS panel',
price=399.99,
inventory=10
)
 
def test_complete_e2e_shopping_flow(self):
# 1. Anonymous user creates a cart
cart_res = self.client.post('/api/v1/carts/', format='json')
self.assertEqual(cart_res.status_code, status.HTTP_201_CREATED)
cart_id = cart_res.data['id']
 
# 2. Add product to cart
add_item_url = f'/api/v1/carts/{cart_id}/items/'
item_res = self.client.post(
add_item_url,
{'product_id': self.product.id, 'quantity': 2},
format='json'
)
self.assertEqual(item_res.status_code, status.HTTP_201_CREATED)
 
# 3. Verify unauthenticated checkout fails
order_url = '/api/v1/orders/'
unauth_order_res = self.client.post(
order_url,
{'cart_id': cart_id, 'shipping_address': '100 Main St, Austin, TX'},
format='json'
)
self.assertEqual(unauth_order_res.status_code, status.HTTP_401_UNAUTHORIZED)
 
# 4. Authenticate user and checkout
self.client.force_authenticate(user=self.user)
order_res = self.client.post(
order_url,
{'cart_id': cart_id, 'shipping_address': '100 Main St, Austin, TX'},
format='json'
)
self.assertEqual(order_res.status_code, status.HTTP_201_CREATED)
 
# 5. Verify database state
self.product.refresh_from_db()
self.assertEqual(self.product.inventory, 8) # 10 - 2
self.assertFalse(Cart.objects.filter(id=cart_id).exists()) # Cart flushed
self.assertEqual(Order.objects.filter(customer=self.user).count(), 1)

2. Verifying Stock Depletion Fails Gracefully

Python
def test_checkout_fails_when_quantity_exceeds_stock(self):
# Create cart and add more than available inventory (15 > 10)
cart = Cart.objects.create()
CartItem.objects.create(cart=cart, product=self.product, quantity=15)
 
self.client.force_authenticate(user=self.user)
response = self.client.post(
'/api/v1/orders/',
{'cart_id': str(cart.id), 'shipping_address': '200 Oak Ave'},
format='json'
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.product.refresh_from_db()
self.assertEqual(self.product.inventory, 10) # Stock untouched

3. Production OpenAPI Documentation Verification

Run the spectacular schema check management command:

Bash / Terminal
python manage.py spectacular --validate --file schema.yml

This verifies that:

  1. 1
    Every serializer field has a valid OpenAPI primitive or component type.
  2. 2
    All custom filters and paginators are documented.
  3. 3
    There are zero schema generator warnings.

4. Summary of DRF Mastery

DomainKey Skills Mastered
FoundationsREST statelessness, HTTP status codes, serializers, serialization/deserialization
Views & RoutingAPIView, Generic Views, ViewSets, DefaultRouter, ModelViewSet
AuthenticationTokenAuth, SimpleJWT, Refresh Tokens, Custom Permissions, Object Permissions
Data Optimizationdjango-filter, SearchFilter, OrderingFilter, PageNumber/Cursor Pagination, select_related
TestingAPITestCase, APIClient, force_authenticate, factory_boy, E2E workflows
Documentationdrf-spectacular, OpenAPI 3.0, Swagger UI, Redoc, @extend_schema

Interactive Quiz

Practice Quiz

Question 1
What does python manage.py spectacular --validate do?
Question 2
In an e-commerce API test, what does self.product.refresh_from_db() guarantee after an order checkout?
Question 3
Why should unauthenticated users be blocked from placing orders (401 Unauthorized)?
Question 4
What happens if a customer attempts to purchase more units than are in stock?
Question 5
What is the main benefit of providing both Swagger UI and Redoc documentation endpoints in production?

Related Lessons

Previous LessonNext Lesson
CRUD, Authentication, Filtering, PaginationNone

Practice Quiz

Test your understanding of this lesson with 5 questions. Each question has one correct answer.

PrevNext