The provided code defines unit tests for a Django application using unittest
and the Django REST Framework (DRF). The tests cover functionality for CustomUser
and Recipe
models, ensuring that various API endpoints behave as expected.
from django.test import TestCase
from rest_framework.test import APIClient
from api_app.models import CustomUser, Recipe
from django.urls import reverse
from rest_framework import status
TestCase
: A Django-provided class to create and run test cases. It sets up a test database and provides methods for assertions.APIClient
: A DRF utility to simulate API requests during testing.CustomUser
andRecipe
: Models from the application being tested.reverse
: Generates URLs from named routes, ensuring changes to route definitions do not break tests.status
: Provides HTTP status codes (e.g.,status.HTTP_200_OK
).
def setUp(self):
self.client = APIClient()
self.test_user = {
'username': 'testuser',
'email': '[email protected]',
'password': 'testpassword',
'bio': 'This is a test bio that is sufficiently long.',
'sex': 'M',
'birthdate': '2000-01-01',
}
user = CustomUser.objects.create(**self.test_user)
user.set_password(self.test_user['password'])
user.save()
setUp
: A method that runs before each test. It initializes test data and anAPIClient
instance.APIClient
: Simulates HTTP requests (GET, POST, etc.) for testing APIs.CustomUser.objects.create
: Creates a newCustomUser
instance using test data.set_password
: Hashes the password for the user before saving.
response = self.client.post(reverse("users-list"), self.test_user_1)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(CustomUser.objects.count(), 2)
- Simulates a POST request to the
users-list
endpoint. - Asserts that the response status is
201 Created
. - Verifies that the total number of users in the database has increased to 2.
response = self.client.get(reverse("users-list"))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(len(response.data), 1)
- Simulates a GET request to fetch all users.
- Verifies that the response is
200 OK
and the returned data contains one user.
response = self.client.post(reverse('user-login'), data={'username': 'testuser', 'password': 'testpassword'})
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIn('token', response.data)
- Tests user login by simulating a POST request with credentials.
- Asserts a
200 OK
response and checks that a token is returned in the response.
self.client.credentials(HTTP_AUTHORIZATION='Token ' + token)
response = self.client.post(reverse('user-logout'))
self.assertEqual(response.status_code, status.HTTP_200_OK)
- Authenticates the user by adding a token to the request header.
- Verifies that the logout request succeeds with a
200 OK
status.
response = self.client.post(reverse("users-list"), self.test_user_1)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
- Ensures that invalid user creation (e.g., username not allowed) returns a
400 Bad Request
response.
self.user = CustomUser.objects.create(**self.test_user)
self.user.set_password(self.test_user['password'])
self.user.save()
self.recipe_data = {
"chef": self.user.id,
"title": "testrecipe",
"description": "a description long enough to pass the test",
"meal_type": "D",
"ingredients": "Test Ingredients to pass the test",
"created_at": "2025-01-10T09:13:48.808495Z",
}
- Creates a test user and a sample recipe for use in recipe-related tests.
response = self.client.post(reverse("recipes-list"), self.recipe_data)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
- Verifies that a valid recipe can be created and returns a
201 Created
status.
response_get = self.client.get(reverse('recipes-list'))
self.assertEqual(response_get.status_code, status.HTTP_200_OK)
- Ensures that fetching all recipes returns a
200 OK
status.
response = self.client.post(reverse("recipes-list"), recipe_data)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
- Ensures invalid recipe creation (e.g., forbidden words in title) returns a
400 Bad Request
.
response = self.client.patch(reverse("recipe-detail", kwargs={"pk": 1}), data=recipe_title)
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
- Tests that unauthorized users cannot update recipes, returning
401 Unauthorized
.
self.client.credentials(HTTP_AUTHORIZATION='Token ' + token)
response = self.client.patch(reverse("recipe-detail", kwargs={"pk": 1}), data=recipe_title)
self.assertEqual(response.status_code, status.HTTP_200_OK)
- Verifies that authorized users can update recipes, returning
200 OK
.
- Error Prevention: Identifies bugs early in the development process.
- Code Integrity: Ensures new changes do not break existing functionality.
- Documentation: Acts as documentation for expected behavior.
- Refactoring Safety: Makes it safer to refactor or optimize code.
- Definition: A utility provided by DRF to simulate HTTP requests during tests.
- Why Use It?
- Enables testing of API endpoints without running a live server.
- Supports various HTTP methods (GET, POST, PUT, PATCH, DELETE).
- Allows setting headers (e.g.,
Authorization
), cookies, and authentication credentials.