How can I properly test swagger_auto_schema for methods, request_body, and responses in drf-yasg with pytest?

I’m working on testing a Django REST Framework (DRF) CartViewSet using pytest, and I need to verify the swagger_auto_schema properties like the HTTP method, request body, and responses for different actions (e.g., add, remove, clear).

I have the following code in my CartViewSet:

class CartViewSet(GenericViewSet, RetrieveModelMixin, ListModelMixin):
    # Other viewset code...

    @swagger_auto_schema(
        method="post",
        request_body=AddToCartSerializer,
        responses={
            201: openapi.Response(description="Item added successfully."),
            400: openapi.Response(description="Invalid input data"),
        },
    )
    @action(detail=False, methods=["post"], url_path="add")
    def add(self, request):
        # Logic for adding an item to the cart
        pass

Now, I want to write a pytest unit test to check the following for the add method:

  1. HTTP Method: Ensure the swagger_auto_schema method is POST.
  2. Request Body: Ensure the correct serializer (AddToCartSerializer) is set for the request body.
  3. Responses: Verify that the response status codes (201 and 400) and their descriptions are properly set.

Could someone guide me on how to properly test the swagger_auto_schema properties for method, request body, and responses in pytest?

Any help or insights would be greatly appreciated!

If you followed the quickstart guide to add drf-yasg to your project you have added the endpoint that returns the whole schema in a json format.

It looks like this:

path('swagger<format>/', schema_view.without_ui(cache_timeout=0), name='schema-json'),

If you call the endpoint locally you can get a payload with everything that's displayed in the swagger UI.

In the payload there is paths field which contains a list of endpoints that exist, under that you have http methods for each of them, as well as possible response codes.

In another field components you can find a list of serializer names.

Now with all of this in mind you can call the endpoint in your tests and assert parts of the response body confirming the changes to the swagger UI.

It's testable like this.

def test_cart_viewset_add_swagger_documentation(self):
        """Test that the CartViewSet's add method has proper Swagger documentation."""
        # Get the add method from CartViewSet
        add_method = CartViewSet.add

        # Access the swagger schema from the method
        schema_info = getattr(add_method, "_swagger_auto_schema", {})

        # The structure has 'post' as the key since it's a POST method
        method_info = schema_info.get("post", {})

        # Verify request body is defined
        request_body = method_info.get("request_body", None)
        assert request_body == AddToCartSerializer

        # Verify responses are defined
        responses = method_info.get("responses", {})
        assert 201 in responses
        assert 400 in responses

        # Verify response content
        success_response = responses.get(201)
        assert isinstance(success_response, openapi.Response)
        assert success_response.description == "Item added successfully."

        error_response = responses.get(400)
        assert isinstance(error_response, openapi.Response)
        assert error_response.description == "Invalid input data"
Back to Top