You don't have access to this class

Keep learning! Join and start boosting your career

Aprovecha el precio especial y haz tu profesión a prueba de IA

Antes: $249

Currency
$209
Suscríbete

Termina en:

2 Días
0 Hrs
2 Min
51 Seg

Pruebas Unitarias para Endpoints Anidados Usando APIClient

20/21
Resources

Unit tests are essential to ensure that our APIs work correctly without having to spend too many resources. Django REST Framework facilitates this process through the APIClient class, which allows us to simulate requests and validate the results easily and efficiently. Next, we will learn how to create unit tests in a Django project using this tool.

How to set up unit tests in Django REST Framework?

To start creating tests in Django REST Framework, we need to work with the test.py file, which is automatically generated when we create a project. In this file, we define our tests by inheriting from the TestCase class, which provides all the functionality needed to run tests in Django.

Within the test class, we use the setUp method to prepare common data that we will reuse in all our tests, such as creating a patient and a doctor. Here, we employ the Django ORM to manage the models easily.

What is the API client and how is it used?

The APIClient client is essential for our tests as it simulates HTTP requests, allowing us to test our API responses without making real requests. This saves us time and resources. In addition, it is automatically configured to work with JSON data, simplifying testing.

We import the client using:

from rest_framework.test import APIClient

This allows us to perform operations such as GET, POST, PUT, and more, directly from our tests. For example, to verify that a list of appointments returns a code 200, we simply write a test that uses the client to make a GET request to the appointments URL.

How do we validate the test results?

Django REST Framework provides the status module, which allows us to check the response codes in a simple way. In the tests, we use the self.assertEqual() method to compare the status code returned by the API with the expected value:

from rest_framework import status self.assertEqual(response.status_code, status.HTTP_200_OK).

This assures us that the API code is working correctly as expected.

How are URLs handled in the tests?

To obtain URLs dynamically in our tests, we use Django's reverse() method, which allows us to construct URLs based on their names. This is especially useful when working with URLs that require parameters, such as IDs.

How do we fix permission errors in our tests?

It is common for some views in the Django REST Framework to require authentication or special permissions. If our tests fail due to permissions, we can adjust the settings in the viewset, making sure that the tests run under the same conditions that real users would face. For example, if only doctors can see certain data, we must make sure that the user in the test has those permissions.

What to do when a test fails unexpectedly?

If a test fails, it is crucial to review the error returned and adjust the code as necessary. Sometimes, the failure may be due to errors in permissions or settings in the viewsets. By correcting these errors and re-running the test, we can validate that the adjustments made have fixed the problem.

Contributions 4

Questions 0

Sort by:

Want to see more contributions, questions and answers from the community?

Hice esta prueba para verificar que un doctor pueda ser puesto en vacaciones: ```js class DoctorViewSetTests(TestCase): def setUp(self): self.patient = Patient.objects.create( first_name='Luis', last_name='Martinez', date_of_birth='1990-12-05', contact_number='12312312', email='[email protected]', address='Dirección de prueba', medical_history='Ninguna', ) self.doctor = Doctor.objects.create( first_name='Oscar', last_name='Barajas', qualification='Profesional', contact_number='23412341234', email='[email protected]', address='Medellín', biography='Sin', is_on_vacation=False, ) self.client = APIClient() def test_set_on_vacation(self): """Prueba para poner un doctor en vacaciones""" url = reverse( 'doctor-set-on-vacation', kwargs={"pk": self.doctor.id}, # Genera la URL para el doctor específico ) # Realizar la solicitud POST para poner al doctor en vacaciones response = self.client.post(url) # Verificar que la respuesta sea 200 OK self.assertEqual(response.status_code, status.HTTP_200_OK) # Refrescar el objeto doctor de la base de datos para verificar el cambio self.doctor.refresh_from_db() # Verificar que el campo 'is_on_vacation' ahora sea True self.assertTrue(self.doctor.is_on_vacation) # Verificar que la respuesta contiene el mensaje adecuado self.assertEqual(response.data['status'], "El doctor está en vacaciones") ```
curso de testing con djago rest framework! its necessary
Para realizar pruebas unitarias de \*\*endpoints anidados\*\* usando `APIClient` en Django REST Framework, puedes simular las solicitudes HTTP a tus endpoints dentro de un contexto de prueba. Aquí te explico cómo hacerlo paso a paso. \### 1. \*\*Escenario: Endpoints Anidados\*\* Supongamos que tienes un endpoint de \*\*doctores\*\* y uno de \*\*pacientes\*\* anidado bajo los doctores. Un ejemplo de URLs anidadas podría ser algo como: \- `/api/doctors/` → Lista de doctores. \- `/api/doctors/{doctor\_id}/patients/` → Lista de pacientes para un doctor en particular. \### 2. \*\*Configuración de las Pruebas\*\* Primero, asegúrate de tener configurado tu `APIClient` y tus modelos. \#### Modelos Si tienes los siguientes modelos: ```python \# models.py from django.db import models class Doctor(models.Model): name = models.CharField(max\_length=100) specialization = models.CharField(max\_length=100) class Patient(models.Model): name = models.CharField(max\_length=100) doctor = models.ForeignKey(Doctor, related\_name='patients', on\_delete=models.CASCADE) ``` \#### Serializers Los serializers podrían verse así: ```python \# serializers.py from rest\_framework import serializers from .models import Doctor, Patient class PatientSerializer(serializers.ModelSerializer): class Meta: model = Patient fields = \['id', 'name'] class DoctorSerializer(serializers.ModelSerializer): patients = PatientSerializer(many=True, read\_only=True) class Meta: model = Doctor fields = \['id', 'name', 'specialization', 'patients'] ``` \#### ViewSets Las vistas para los endpoints anidados: ```python \# views.py from rest\_framework import viewsets from .models import Doctor, Patient from .serializers import DoctorSerializer, PatientSerializer class DoctorViewSet(viewsets.ModelViewSet): queryset = Doctor.objects.all() serializer\_class = DoctorSerializer class PatientViewSet(viewsets.ModelViewSet): serializer\_class = PatientSerializer def get\_queryset(self): return Patient.objects.filter(doctor\_id=self.kwargs\['doctor\_pk']) ``` Y en el archivo de \*\*urls.py\*\*: ```python from rest\_framework.routers import DefaultRouter from .views import DoctorViewSet, PatientViewSet router = DefaultRouter() router.register(r'doctors', DoctorViewSet) \# URL anidadas para pacientes de un doctor específico from rest\_framework\_nested import routers doctor\_router = routers.NestedSimpleRouter(router, r'doctors', lookup='doctor') doctor\_router.register(r'patients', PatientViewSet, basename='doctor-patients') urlpatterns = router.urls + doctor\_router.urls ``` \### 3. \*\*Prueba de Endpoints Anidados\*\* Para realizar una prueba unitaria sobre los endpoints anidados usando `APIClient`, sigue los pasos siguientes: \#### Crear el archivo de pruebas ```python \# tests.py from rest\_framework.test import APITestCase, APIClient from django.urls import reverse from rest\_framework import status from .models import Doctor, Patient class DoctorPatientAPITests(APITestCase): def setUp(self): self.client = APIClient() \# Crear un doctor y pacientes self.doctor = Doctor.objects.create(name="Dr. Smith", specialization="Cardiology") self.patient1 = Patient.objects.create(name="John Doe", doctor=self.doctor) self.patient2 = Patient.objects.create(name="Jane Doe", doctor=self.doctor) \# URL para obtener la lista de pacientes de un doctor específico self.patients\_url = reverse('doctor-patients-list', kwargs={'doctor\_pk': self.doctor.id}) def test\_get\_patients\_for\_doctor(self): """Prueba para obtener la lista de pacientes de un doctor específico""" \# Simular una solicitud GET al endpoint de pacientes response = self.client.get(self.patients\_url) \# Comprobar que la respuesta tenga código 200 (éxito) self.assertEqual(response.status\_code, status.HTTP\_200\_OK) \# Verificar que los pacientes se devuelvan correctamente en la respuesta self.assertEqual(len(response.data), 2) self.assertEqual(response.data\[0]\['name'], self.patient1.name) self.assertEqual(response.data\[1]\['name'], self.patient2.name) def test\_create\_patient\_for\_doctor(self): """Prueba para crear un paciente bajo un doctor específico""" \# Datos para el nuevo paciente data = { 'name': 'Tom Doe' } \# Simular una solicitud POST al endpoint de pacientes response = self.client.post(self.patients\_url, data, format='json') \# Comprobar que la respuesta tenga código 201 (creado) self.assertEqual(response.status\_code, status.HTTP\_201\_CREATED) \# Verificar que el paciente fue creado correctamente y asociado al doctor self.assertEqual(Patient.objects.filter(doctor=self.doctor).count(), 3) self.assertEqual(response.data\['name'], 'Tom Doe') ``` \### Explicación de la Prueba 1\. \*\*`setUp`\*\*: Configuramos el cliente de la API (`APIClient`), creamos un `Doctor` y dos `Patient`. También generamos la URL de los pacientes anidados bajo un doctor específico. 2\. \*\*`test\_get\_patients\_for\_doctor`\*\*: \- Enviamos una solicitud GET al endpoint anidado `/doctors/{doctor\_id}/patients/`. \- Verificamos que la respuesta tenga código de estado `200 OK`. \- Comprobamos que se devuelvan los pacientes correctos en la respuesta. 3\. \*\*`test\_create\_patient\_for\_doctor`\*\*: \- Enviamos una solicitud POST para crear un nuevo paciente bajo el doctor. \- Verificamos que el código de estado sea `201 CREATED`. \- Comprobamos que el paciente fue correctamente añadido a la base de datos y asociado al doctor. \### 4. \*\*Ejecutar las pruebas\*\* Para ejecutar las pruebas, utiliza el siguiente comando en la terminal: ```bash python manage.py test ``` Esto ejecutará las pruebas en tu proyecto y validará que los endpoints anidados funcionen correctamente.
Podemos hacer Test similando el login. Aquí les dejo mis pruebas unitartias para doctor. `from datetime import datefrom django.urls import reversefrom django.test import TestCasefrom patients.models import Patientfrom .models import Doctor` `from rest_framework.test import APIClientfrom rest_framework.test import APITestCasefrom rest_framework import status` `from django.contrib.auth.models import User, Group` `# Create your tests here.` `class DoctorViewSetTest(TestCase): def setUp(self): self.patient = Patient.objects.create( first_name="Juan", last_name="Sarango", date_of_birth=date(1940, 1, 1), contact_number="123456789", email="[email protected]", address="Calle de la Paz, 1", medical_history="No tengo historia de medicina", )` ` self.doctor = Doctor.objects.create( first_name="Jorge", last_name="Lozano", qualification="Medico", contact_number="123456789", graduation_date=date(2020, 1, 1), email="[email protected]", address="Calle de la Paz, 1", biography="Medico especialista en cardiología", is_on_vacation=False, )` ` self.group = Group.objects.create(name="doctors") self.user = User.objects.create_user( username="doctor", password="doctor", ) self.user.groups.add(self.group)` ` self.client = APIClient()` ` def test_list_should_return_403(self): url = reverse("doctors-appointments", kwargs={"pk": self.doctor.id}) response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)` ` def test_list_should_return_200(self): url = reverse("doctors-appointments", kwargs={"pk": self.doctor.id}) self.client.login(username="doctor", password="doctor") response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK)` ` def test_should_return_doctor_detail(self): url = reverse("doctors-detail", kwargs={"pk": self.doctor.id}) self.client.login(username="doctor", password="doctor") response = self.client.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data["id"], self.doctor.id)` ` def test_put_doctor_on_vacation(self): url = reverse("doctors-toggle-is-on-vacation", kwargs={"pk": self.doctor.id}) self.client.login(username="doctor", password="doctor") response = self.client.post(url, data={"is_on_vacation": True}) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data, "El doctor está de vacaciones")` ` def test_put_doctor_off_vacation(self): url = reverse("doctors-toggle-off-vacation", kwargs={"pk": self.doctor.id}) self.client.login(username="doctor", password="doctor") response = self.client.post(url, data={"is_on_vacation": False}) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data, "El doctor NO está de vacaciones")` ` def test_apointment(self): url = reverse("doctors-appointments", kwargs={"pk": self.doctor.id}) self.client.login(username="doctor", password="doctor") appointment = { "appointment_date": "2024-01-10", "appointment_time": "10:00:00", "notes": "Cita agendada", "status": "confirmed", "patient": self.patient.id, "doctor": self.doctor.id, } response = self.client.post(url, data=appointment)` ` self.assertEqual(response.status_code, status.HTTP_201_CREATED)` ` def test_apointment_should_return_403(self): url = reverse("doctors-appointments", kwargs={"pk": self.doctor.id}) appointment = { "appointment_date": "2024-01-10", "appointment_time": "10:00:00", "notes": "Cita agendada", "status": "confirmed", "patient": self.patient.id, "doctor": self.doctor.id, } response = self.client.post(url, data=appointment)` ` self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)`