Guides

APITestCase

Guide to the declarative testing of API views

APITestCase

class APITestCase(TestCase)

A subclass of Django's TestCase that provides methods for testing Django REST
API views declaratively using test scenarios.

Designed to be used with the APIViewTestScenario class, each scenario can
include the request components (path/query parameters, request body/headers),
the expected response components (status code, response body type/content), and
extra assertions to be made on the response.

This class provides methods for sending requests to the API view, asserting that
a scenario succeed, and asserting that multiple scenarios succeed. It also includes
methods for making assertions on the response, such as checking the status code,
validating the response body type, and comparing the response body to the expected
response body.

Example:

from rest_testing import APITestCase, APIViewTestScenario

class TestObjectAPI(APITestCase):
    def test_read_object(self):
        self.assertScenariosSucceed(
            method="GET",
            path="/api/objects/{id}",
            scenarios=[
                APIViewTestScenario(
                    path_parameters={"id": 1},
                    request_headers={"HTTP_AUTHORIZATION": "Bearer 123"},
                    expected_response_status=200,
                    expected_response_body='{"id": 1, "name": "object-1"}',
                ),
                APIViewTestScenario(
                    path_parameters={"id": 2},
                    request_headers={"HTTP_AUTHORIZATION": "Bearer 123"},
                    expected_response_status=404,
                ),
                APIViewTestScenario(
                    path_parameters={"id": 2},
                    request_headers={"HTTP_AUTHORIZATION": "Bearer 456"},
                    expected_response_status=403,
                ),
                APIViewTestScenario(
                    path_parameters={"id": 2},
                    request_headers={},
                    expected_response_status=401,
                ),
            ],
        )

Notes:

When testing multiple scenarios, each scenario is run in a subtest and in a
separate transaction savepoint to ensure that the scenarios are independent.
The database changes are rolled back between each scenario to prevent side
effects between scenarios.

send_request

def send_request(
        method: str,
        path: str,
        path_parameters: Optional[Dict[str, Any]] = None,
        query_parameters: Optional[Dict[str, Any]] = None,
        request_body: Optional[Dict[str, Any]] = None,
        request_headers: Optional[Dict[str, Any]] = None) -> HttpResponse

Send a request to the API view with the given method, path, path parameters,
query parameters, request body, and request headers.

Arguments:

  • method(str) - The HTTP method of the request.
  • path(str) - The path of the request.
    path_parameters(dict, optional): The path parameters of the request.
    query_parameters(dict, optional): The query parameters of the request.
    request_body(dict, optional): The request body of the request.
    request_headers(dict, optional): The request headers of the request.

Returns:

  • HttpResponse - The response of the request.

Example:

response = self.send_request(
    method="POST",
    path="/api/objects/{id}",
    path_parameters={"id": 1},
    query_parameters={},
    request_body={"name": "new name"},
    request_headers={"HTTP_AUTHORIZATION": "Bearer 123"},
)

assertScenarioSucceed

def assertScenarioSucceed(
    method: str,
    path: str,
    scenario: APIViewTestScenario[ResponseBodyType],
    default_assertions: Optional[Callable[
        [HttpResponse, APIViewTestScenario[ResponseBodyType]], None]] = None
) -> None

Assert that the given scenario succeeds when sent to the API view with the
given method and path.

Arguments:

  • method(str) - The HTTP method of the request.
  • path(str) - The path of the request.
  • scenario(APIViewTestScenario) - The scenario to test.
    default_assertions(callable, optional): The default assertions to make on
    the response if no assertions are provided in the scenario.

Example:

self.assertScenarioSucceed(
    method="GET",
    path="/api/objects/{id}",
    scenario=APIViewTestScenario(
        path_parameters={"id": 1},
        request_headers={"HTTP_AUTHORIZATION": "Bearer 123"},
        expected_response_status=200,
        expected_response_body='{"id": 1, "name": "object-1"}',
    ),
)

assertScenariosSucceed

def assertScenariosSucceed(
    method: str,
    path: str,
    scenarios: List[APIViewTestScenario[ResponseBodyType]],
    default_assertions: Optional[Callable[
        [HttpResponse, APIViewTestScenario[ResponseBodyType]], None]] = None
) -> None

Assert that the given scenarios succeed when sent to the API view with the
given method and path.

This method runs each scenario in a separate transaction savepoint to ensure
that the scenarios are independent, and rolls back the database changes between
each scenario.

Arguments:

  • method(str) - The HTTP method of the request.
  • path(str) - The path of the request.
  • scenarios(List[APIViewTestScenario]) - The scenarios to test.
    default_assertions(callable, optional): The default assertions to make on
    the response if no assertions are provided in the scenarios.

Example:

self.assertScenariosSucceed(
    method="DELETE",
    path="/api/objects/{id}",
    scenarios=[
        APIViewTestScenario(
            path_parameters={"id": 1},
            request_headers={"HTTP_AUTHORIZATION": "Bearer 123"},
            expected_response_status=204,
        ),
        APIViewTestScenario(
            path_parameters={"id": 1},
            request_headers={"HTTP_AUTHORIZATION": "Bearer 456"},
            expected_response_status=204,
        ),
        APIViewTestScenario(
            path_parameters={"id": 1},
            request_headers={"HTTP_AUTHORIZATION": "Bearer 789"},
            expected_response_status=204,
        ),
    ],
)