Skip to content

Latest commit

 

History

History
211 lines (149 loc) · 6.14 KB

day_6.md

File metadata and controls

211 lines (149 loc) · 6.14 KB

Code Explanation

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.


1. Imports

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 and Recipe: 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).

2. User Tests

Setup

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 an APIClient instance.
  • APIClient: Simulates HTTP requests (GET, POST, etc.) for testing APIs.
  • CustomUser.objects.create: Creates a new CustomUser instance using test data.
  • set_password: Hashes the password for the user before saving.

Test Cases

Test User Creation
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.

Test Get All Users
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.

Test Login 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.

Test Logout User
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.

Invalid User Creation

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.

3. Recipe Tests

Setup

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.

Test Recipe Creation

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.

Test Get All Recipes

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.

Invalid Recipe Creation

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.

Test Recipe Update Without Login

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.

Test Recipe Update With Login

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.

Why Unit Testing Is Important

  1. Error Prevention: Identifies bugs early in the development process.
  2. Code Integrity: Ensures new changes do not break existing functionality.
  3. Documentation: Acts as documentation for expected behavior.
  4. Refactoring Safety: Makes it safer to refactor or optimize code.

What is APIClient?

  • 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.