{"id":19115266,"url":"https://github.com/saadmk11/drf-test-generator","last_synced_at":"2025-10-04T10:51:14.745Z","repository":{"id":131856708,"uuid":"611325808","full_name":"saadmk11/drf-test-generator","owner":"saadmk11","description":"A Django Package that generates basic unittest and pytest style tests for Django REST Framework ViewSets","archived":false,"fork":false,"pushed_at":"2024-09-07T14:00:16.000Z","size":44,"stargazers_count":29,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-20T22:46:18.565Z","etag":null,"topics":["automation","django","django-rest-framework","django-rest-framework-testing","django-test","django-testing","pytest","pytest-django","python","python3","rest-framework","test-generation","test-generator","unittest"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/drf-test-generator/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/saadmk11.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-03-08T15:40:21.000Z","updated_at":"2025-08-15T20:20:51.000Z","dependencies_parsed_at":null,"dependency_job_id":"c6424a98-93d5-4779-b606-469b0b3e9f69","html_url":"https://github.com/saadmk11/drf-test-generator","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/saadmk11/drf-test-generator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saadmk11%2Fdrf-test-generator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saadmk11%2Fdrf-test-generator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saadmk11%2Fdrf-test-generator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saadmk11%2Fdrf-test-generator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/saadmk11","download_url":"https://codeload.github.com/saadmk11/drf-test-generator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saadmk11%2Fdrf-test-generator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278302556,"owners_count":25964520,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-04T02:00:05.491Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["automation","django","django-rest-framework","django-rest-framework-testing","django-test","django-testing","pytest","pytest-django","python","python3","rest-framework","test-generation","test-generator","unittest"],"created_at":"2024-11-09T04:45:56.018Z","updated_at":"2025-10-04T10:51:14.739Z","avatar_url":"https://github.com/saadmk11.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# drf-test-generator\n\n[![Pypi Version](https://img.shields.io/pypi/v/drf-test-generator.svg?style=flat-square)](https://pypi.org/project/drf-test-generator/)\n[![Supported Python Versions](https://img.shields.io/pypi/pyversions/drf-test-generator?style=flat-square)](https://pypi.org/project/drf-test-generator/)\n[![Supported Django Versions](https://img.shields.io/pypi/frameworkversions/django/drf-test-generator?color=darkgreen\u0026style=flat-square)](https://pypi.org/project/drf-test-generator/)\n[![License](https://img.shields.io/github/license/saadmk11/drf-test-generator?style=flat-square)](https://github.com/saadmk11/drf-test-generator/blob/main/LICENSE)\n\n![Django Tests](https://img.shields.io/github/actions/workflow/status/saadmk11/drf-test-generator/test.yaml?style=flat-square)\n![Codecov](https://img.shields.io/codecov/c/github/saadmk11/drf-test-generator?style=flat-square\u0026token=ugjHXbEKib)\n![pre-commit.ci](https://img.shields.io/badge/pre--commit.ci-enabled-brightgreen?logo=pre-commit\u0026logoColor=white\u0026style=flat-square)\n![Code Style](https://img.shields.io/badge/Code%20Style-Black-black?style=flat-square)\n\nA Django Package that generates basic tests for Django REST Framework.\nIt can generate both `unittest` and `pytest` Style tests for all `ViewSets` in a Django REST Framework `router`.\n\n# Features\n\n- Generates tests for all `ViewSets` in a Django REST Framework `router`\n- Generates tests for all custom `actions` in a `ViewSet`\n- Generates tests for all `HTTP` methods in a `ViewSet`\n- Supports test generation for both `pytest` and `unittest`\n\n# Requirements\n\n- Python 3.8+\n- Django 4.2+\n- Django REST Framework 3.12+\n\n# Installation\n\n```console\npip install drf-test-generator\n```\n\n# Setup\n\nAdd `drf_test_generator` to your `INSTALLED_APPS` in `settings.py`:\n\n```python\nINSTALLED_APPS = [\n    # ...\n    \"drf_test_generator\",\n]\n```\n\n**Note:** This is required for the Django Management Command. You can remove it from `INSTALLED_APPS` once you have generated the tests.\n\n# Generate Tests\n\n## Django Management Command\n\nYou can generate tests using the Django Management Command:\n\n```console\npython manage.py generate_viewset_tests -r api.urls.router\n```\n\n**Note:** Currently this package only supports test generation for ViewSets that are registered in a router.\n\n## Django Management Command Options\n\n### `-r` or `--router` (REQUIRED)\n\nThe dotted path to the REST framework url router. This is the router that contains the ViewSets you want to generate tests for.\n\n**Example:** `--router api.urls.router`\n\n### `--test-base-class`\n\nThe 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`.\n\n**Example:** `--test-base-class tests.base.MyCustomTest`\n\n### `--namespace`\n\nThe namespace to use for the URLs (e.g: `api_v1:posts-list` ). If not provided, no namespace will be used.\n\n**Example:** `--namespace api_v1`\n\n### `--output-file`\n\nThe path to the output file. If not provided, the tests will be printed to the console.\n\n**Example:** `--output-file tests.py`\n\n### `--select-viewsets`\n\nA list of ViewSets to generate tests for. If not provided, tests will be generated for all ViewSets in the router.\n\n**Example:** `--select-viewsets PostViewSet CommentViewSet`\n\n### `--variant`\n\nThe test variant to generate. Options: `pytest`, `unittest`. If not provided, `unittest` will be used.\n\n**Example:** `--variant pytest`\n\n### `--pytest-markers`\n\nA list of pytest markers to add to the generated tests. If not provided, only the `@pytest.mark.django_db` marker will be added.\n\n**Example:** `--pytest-markers pytest.mark.ignore_template_errors pytest.mark.urls('myapp.test_urls')`\n\n### `--pytest-fixtures`\n\nA list of pytest fixtures to add to the generated tests. If not provided, only the `client` fixture will be added.\n\n**Example:** `--pytest-fixtures django_user_model`\n\n# Examples Usage\n\n## For the following code\n\n```python\n# api/views.py\nfrom rest_framework import viewsets\nfrom rest_framework.decorators import action\nfrom rest_framework.response import Response\n\n\nclass PostViewSet(viewsets.ModelViewSet):\n    # ...\n    @action(detail=False, methods=[\"get\", \"post\"], url_path=\"custom-action\")\n    def custom_action(self, request):\n        return Response()\n\n    @action(detail=True, methods=[\"get\", \"options\", \"put\"], url_path=\"new-action\")\n    def custom_action2(self, request):\n        return Response()\n\n\n# api/urls.py\nfrom rest_framework import routers\n\nrouter = routers.DefaultRouter()\n\nrouter.register(\"posts\", PostViewSet, basename=\"post\")\n```\n\n## For Unittest\n\n**Run Command**\n\n```console\npython manage.py generate_viewset_tests -r api.urls.router\n```\n\n**Output**\n\n```python\nfrom django.urls import reverse\n\nfrom rest_framework import status\n\nfrom rest_framework.test import APITestCase\n\n\nclass PostViewSetTests(APITestCase):\n    def test_post_list_get(self):\n        url = reverse(\"post-list\")\n        response = self.client.get(url)\n        self.assertEqual(response.status_code, status.HTTP_200_OK)\n\n    def test_post_create_post(self):\n        url = reverse(\"post-list\")\n        response = self.client.post(url, data={})\n        self.assertEqual(response.status_code, status.HTTP_201_CREATED)\n\n    def test_post_custom_action_get(self):\n        url = reverse(\"post-custom-action\")\n        response = self.client.get(url)\n        self.assertEqual(response.status_code, status.HTTP_200_OK)\n\n    def test_post_custom_action_post(self):\n        url = reverse(\"post-custom-action\")\n        response = self.client.post(url, data={})\n        self.assertEqual(response.status_code, status.HTTP_201_CREATED)\n\n    def test_post_retrieve_get(self):\n        url = reverse(\"post-detail\", kwargs={\"pk\": None})\n        response = self.client.get(url)\n        self.assertEqual(response.status_code, status.HTTP_200_OK)\n\n    def test_post_update_put(self):\n        url = reverse(\"post-detail\", kwargs={\"pk\": None})\n        response = self.client.put(url, data={})\n        self.assertEqual(response.status_code, status.HTTP_200_OK)\n\n    def test_post_partial_update_patch(self):\n        url = reverse(\"post-detail\", kwargs={\"pk\": None})\n        response = self.client.patch(url, data={})\n        self.assertEqual(response.status_code, status.HTTP_200_OK)\n\n    def test_post_destroy_delete(self):\n        url = reverse(\"post-detail\", kwargs={\"pk\": None})\n        response = self.client.delete(url)\n        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)\n\n    def test_post_custom_action2_get(self):\n        url = reverse(\"post-custom-action2\", kwargs={\"pk\": None})\n        response = self.client.get(url)\n        self.assertEqual(response.status_code, status.HTTP_200_OK)\n\n    def test_post_custom_action2_options(self):\n        url = reverse(\"post-custom-action2\", kwargs={\"pk\": None})\n        response = self.client.options(url)\n        self.assertEqual(response.status_code, status.HTTP_200_OK)\n\n    def test_post_custom_action2_put(self):\n        url = reverse(\"post-custom-action2\", kwargs={\"pk\": None})\n        response = self.client.put(url, data={})\n        self.assertEqual(response.status_code, status.HTTP_200_OK)\n```\n\n## For Pytest\n\n**Run Command**\n\n```console\npython manage.py generate_viewset_tests -r api.urls.router --variant pytest\n```\n\n**Output**\n\n```python\nfrom django.urls import reverse\n\nfrom rest_framework import status\n\nimport pytest\n\n# PostViewSet Tests\n\n\n@pytest.mark.django_db\ndef test_post_list_get(client):\n    url = reverse(\"post-list\")\n    response = client.get(url)\n    assert response.status_code == status.HTTP_200_OK\n\n\n@pytest.mark.django_db\ndef test_post_create_post(client):\n    url = reverse(\"post-list\")\n    response = client.post(url, data={})\n    assert response.status_code == status.HTTP_201_CREATED\n\n\n@pytest.mark.django_db\ndef test_post_custom_action_get(client):\n    url = reverse(\"post-custom-action\")\n    response = client.get(url)\n    assert response.status_code == status.HTTP_200_OK\n\n\n@pytest.mark.django_db\ndef test_post_custom_action_post(client):\n    url = reverse(\"post-custom-action\")\n    response = client.post(url, data={})\n    assert response.status_code == status.HTTP_201_CREATED\n\n\n@pytest.mark.django_db\ndef test_post_retrieve_get(client):\n    url = reverse(\"post-detail\", kwargs={\"pk\": None})\n    response = client.get(url)\n    assert response.status_code == status.HTTP_200_OK\n\n\n@pytest.mark.django_db\ndef test_post_update_put(client):\n    url = reverse(\"post-detail\", kwargs={\"pk\": None})\n    response = client.put(url, data={})\n    assert response.status_code == status.HTTP_200_OK\n\n\n@pytest.mark.django_db\ndef test_post_partial_update_patch(client):\n    url = reverse(\"post-detail\", kwargs={\"pk\": None})\n    response = client.patch(url, data={})\n    assert response.status_code == status.HTTP_200_OK\n\n\n@pytest.mark.django_db\ndef test_post_destroy_delete(client):\n    url = reverse(\"post-detail\", kwargs={\"pk\": None})\n    response = client.delete(url)\n    assert response.status_code == status.HTTP_204_NO_CONTENT\n\n\n@pytest.mark.django_db\ndef test_post_custom_action2_get(client):\n    url = reverse(\"post-custom-action2\", kwargs={\"pk\": None})\n    response = client.get(url)\n    assert response.status_code == status.HTTP_200_OK\n\n\n@pytest.mark.django_db\ndef test_post_custom_action2_options(client):\n    url = reverse(\"post-custom-action2\", kwargs={\"pk\": None})\n    response = client.options(url)\n    assert response.status_code == status.HTTP_200_OK\n\n\n@pytest.mark.django_db\ndef test_post_custom_action2_put(client):\n    url = reverse(\"post-custom-action2\", kwargs={\"pk\": None})\n    response = client.put(url, data={})\n    assert response.status_code == status.HTTP_200_OK\n```\n\n# License\n\nThe code in this project is released under the [MIT License](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaadmk11%2Fdrf-test-generator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsaadmk11%2Fdrf-test-generator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaadmk11%2Fdrf-test-generator/lists"}