Skip to main content

A Django app to generate basic tests for Django Rest Framework

Project description

drf-test-generator

Pypi Version Supported Python Versions Supported Django Versions License

Django Tests Codecov pre-commit.ci Code Style

A Django Package that generates basic tests for Django REST Framework. It can generate both unittest and pytest Style tests for all ViewSets in a Django REST Framework router.

Features

  • Generates tests for all ViewSets in a Django REST Framework router
  • Generates tests for all custom actions in a ViewSet
  • Generates tests for all HTTP methods in a ViewSet
  • Supports test generation for both pytest and unittest

Requirements

  • Python 3.8+
  • Django 4.2+
  • Django REST Framework 3.12+

Installation

pip install drf-test-generator

Setup

Add drf_test_generator to your INSTALLED_APPS in settings.py:

INSTALLED_APPS = [
    # ...
    "drf_test_generator",
]

Note: This is required for the Django Management Command. You can remove it from INSTALLED_APPS once you have generated the tests.

Generate Tests

Django Management Command

You can generate tests using the Django Management Command:

python manage.py generate_viewset_tests -r api.urls.router

Note: Currently this package only supports test generation for ViewSets that are registered in a router.

Django Management Command Options

-r or --router (REQUIRED)

The dotted path to the REST framework url router. This is the router that contains the ViewSets you want to generate tests for.

Example: --router api.urls.router

--test-base-class

The dotted path to the test base class. This is the class that your tests will inherit from. If not provided, the tests will inherit from rest_framework.test.APITestCase.

Example: --test-base-class tests.base.MyCustomTest

--namespace

The namespace to use for the URLs (e.g: api_v1:posts-list ). If not provided, no namespace will be used.

Example: --namespace api_v1

--output-file

The path to the output file. If not provided, the tests will be printed to the console.

Example: --output-file tests.py

--select-viewsets

A list of ViewSets to generate tests for. If not provided, tests will be generated for all ViewSets in the router.

Example: --select-viewsets PostViewSet CommentViewSet

--variant

The test variant to generate. Options: pytest, unittest. If not provided, unittest will be used.

Example: --variant pytest

--pytest-markers

A list of pytest markers to add to the generated tests. If not provided, only the @pytest.mark.django_db marker will be added.

Example: --pytest-markers pytest.mark.ignore_template_errors pytest.mark.urls('myapp.test_urls')

--pytest-fixtures

A list of pytest fixtures to add to the generated tests. If not provided, only the client fixture will be added.

Example: --pytest-fixtures django_user_model

Examples Usage

For the following code

# api/views.py
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response


class PostViewSet(viewsets.ModelViewSet):
    # ...
    @action(detail=False, methods=["get", "post"], url_path="custom-action")
    def custom_action(self, request):
        return Response()

    @action(detail=True, methods=["get", "options", "put"], url_path="new-action")
    def custom_action2(self, request):
        return Response()


# api/urls.py
from rest_framework import routers

router = routers.DefaultRouter()

router.register("posts", PostViewSet, basename="post")

For Unittest

Run Command

python manage.py generate_viewset_tests -r api.urls.router

Output

from django.urls import reverse

from rest_framework import status

from rest_framework.test import APITestCase


class PostViewSetTests(APITestCase):
    def test_post_list_get(self):
        url = reverse("post-list")
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_post_create_post(self):
        url = reverse("post-list")
        response = self.client.post(url, data={})
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

    def test_post_custom_action_get(self):
        url = reverse("post-custom-action")
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_post_custom_action_post(self):
        url = reverse("post-custom-action")
        response = self.client.post(url, data={})
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

    def test_post_retrieve_get(self):
        url = reverse("post-detail", kwargs={"pk": None})
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_post_update_put(self):
        url = reverse("post-detail", kwargs={"pk": None})
        response = self.client.put(url, data={})
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_post_partial_update_patch(self):
        url = reverse("post-detail", kwargs={"pk": None})
        response = self.client.patch(url, data={})
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_post_destroy_delete(self):
        url = reverse("post-detail", kwargs={"pk": None})
        response = self.client.delete(url)
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)

    def test_post_custom_action2_get(self):
        url = reverse("post-custom-action2", kwargs={"pk": None})
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_post_custom_action2_options(self):
        url = reverse("post-custom-action2", kwargs={"pk": None})
        response = self.client.options(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

    def test_post_custom_action2_put(self):
        url = reverse("post-custom-action2", kwargs={"pk": None})
        response = self.client.put(url, data={})
        self.assertEqual(response.status_code, status.HTTP_200_OK)

For Pytest

Run Command

python manage.py generate_viewset_tests -r api.urls.router --variant pytest

Output

from django.urls import reverse

from rest_framework import status

import pytest

# PostViewSet Tests


@pytest.mark.django_db
def test_post_list_get(client):
    url = reverse("post-list")
    response = client.get(url)
    assert response.status_code == status.HTTP_200_OK


@pytest.mark.django_db
def test_post_create_post(client):
    url = reverse("post-list")
    response = client.post(url, data={})
    assert response.status_code == status.HTTP_201_CREATED


@pytest.mark.django_db
def test_post_custom_action_get(client):
    url = reverse("post-custom-action")
    response = client.get(url)
    assert response.status_code == status.HTTP_200_OK


@pytest.mark.django_db
def test_post_custom_action_post(client):
    url = reverse("post-custom-action")
    response = client.post(url, data={})
    assert response.status_code == status.HTTP_201_CREATED


@pytest.mark.django_db
def test_post_retrieve_get(client):
    url = reverse("post-detail", kwargs={"pk": None})
    response = client.get(url)
    assert response.status_code == status.HTTP_200_OK


@pytest.mark.django_db
def test_post_update_put(client):
    url = reverse("post-detail", kwargs={"pk": None})
    response = client.put(url, data={})
    assert response.status_code == status.HTTP_200_OK


@pytest.mark.django_db
def test_post_partial_update_patch(client):
    url = reverse("post-detail", kwargs={"pk": None})
    response = client.patch(url, data={})
    assert response.status_code == status.HTTP_200_OK


@pytest.mark.django_db
def test_post_destroy_delete(client):
    url = reverse("post-detail", kwargs={"pk": None})
    response = client.delete(url)
    assert response.status_code == status.HTTP_204_NO_CONTENT


@pytest.mark.django_db
def test_post_custom_action2_get(client):
    url = reverse("post-custom-action2", kwargs={"pk": None})
    response = client.get(url)
    assert response.status_code == status.HTTP_200_OK


@pytest.mark.django_db
def test_post_custom_action2_options(client):
    url = reverse("post-custom-action2", kwargs={"pk": None})
    response = client.options(url)
    assert response.status_code == status.HTTP_200_OK


@pytest.mark.django_db
def test_post_custom_action2_put(client):
    url = reverse("post-custom-action2", kwargs={"pk": None})
    response = client.put(url, data={})
    assert response.status_code == status.HTTP_200_OK

License

The code in this project is released under the MIT License.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

drf_test_generator-0.0.6.tar.gz (12.3 kB view details)

Uploaded Source

Built Distribution

drf_test_generator-0.0.6-py3-none-any.whl (9.3 kB view details)

Uploaded Python 3

File details

Details for the file drf_test_generator-0.0.6.tar.gz.

File metadata

  • Download URL: drf_test_generator-0.0.6.tar.gz
  • Upload date:
  • Size: 12.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.12.5

File hashes

Hashes for drf_test_generator-0.0.6.tar.gz
Algorithm Hash digest
SHA256 e487d23d98de22559d2c69d4bd915b373b0d5252fa36aedf4dd09e1fa458b6b8
MD5 4c0246f8ac515bfee2864798ebc354dd
BLAKE2b-256 32cd3a6caca1f845ab1c76963c5f87aef9df09dca769bae173674240ec9e2fa0

See more details on using hashes here.

File details

Details for the file drf_test_generator-0.0.6-py3-none-any.whl.

File metadata

File hashes

Hashes for drf_test_generator-0.0.6-py3-none-any.whl
Algorithm Hash digest
SHA256 ed1ca1bbb7fd00613889802dcf55ba5c4a11b5cd8fa2f1f91af1979c8023fe0f
MD5 c1d6d2316b8c076001351669f06061f5
BLAKE2b-256 29d82ec621fe4fcd3c81e6d208e684d54beaf25f40b56c6958b8bffa73f825e3

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page