Regístrate para acceder a más de 15 cursos gratuitos de programación con un simulador

Pruebas de integración Desarrollo con el framework Django

Vamos a aprender a comprobar que nuestra aplicación con Django realmente funciona. Ya hemos avanzado bastante en el curso, así que es un buen momento para introducir las pruebas de integración, es decir, verificar que la app funciona "como lo haría un usuario". Lo haremos paso a paso, de forma sencilla.


¿Qué son las pruebas de integración?

Cuando desarrollamos con Django, creamos partes que deben funcionar juntas: modelos, vistas, rutas, formularios, etc. Una prueba de integración revisa cómo interactúan todas estas partes desde el punto de vista de un usuario. No probamos un pedacito, sino toda la funcionalidad: desde que se hace un pedido (una solicitud HTTP) hasta que vuelve la respuesta.

En Django no necesitamos un servidor encendido para esto: usamos una herramienta llamada client, que simula solicitudes internas rápidas.


Primer ejemplo: Listar usuarios

Supongamos que tenemos un sitio con un recurso en la URL /users/ donde se lista un grupo de usuarios registrados. Vamos a escribir un test para verificar que este recurso funciona.

Esta es la estructura básica de archivos para una app llamada users dentro de un proyecto:

.
├── manage.py
└── simple_blog
    ├── users
    │   ├── models.py
    │   ├── views.py
    │   ├── urls.py
    │   ├── tests.py

Código del test

📁 Archivo: users/tests.py

from django.test import TestCase
from django.urls import reverse

class UsersTest(TestCase):
    def test_users_list(self):
        # Simulamos una solicitud GET a la ruta "users:index"
        response = self.client.get(reverse("users:index"))

        # Verificamos que la respuesta tenga estado 200 (OK)
        self.assertEqual(response.status_code, 200)

¿Qué está pasando aquí?

  • Usamos reverse("users:index") para obtener la URL con nombre users:index.
  • El método self.client.get() simula una solicitud GET.
  • Luego usamos assertEqual() para asegurarnos que la respuesta fue 200, lo cual significa "todo bien".

❗ Pero ojo, eso no nos dice que el contenido sea correcto… solo que hubo respuesta.


Verificar el contenido

Si esperas que se muestre una lista de usuarios, tienes que verificar eso también.

def test_users_list(self):
        response = self.client.get(reverse("users:index"))
        self.assertEqual(response.status_code, 200)

        # Verificamos que haya 'users' dentro del contexto
        self.assertIn('users', response.context)

        # Verificamos que la lista no esté vacía
        users = response.context['users']
        self.assertTrue(len(users) > 0)

Con estas líneas, estamos verificando que la vista devolvió una lista de usuarios y que esa lista no está vacía.


Cómo ejecutar los tests

Desde la terminal:

uv run manage.py test

Eso:

  • Crea una base de datos temporal de prueba
  • Corre todos los tests
  • Borra la base temporal al terminar

Trabajando con la base de datos

Ahora vamos a un ejemplo más interesante: actualizar datos. Pero, para probarlo necesitamos crear datos de prueba antes. Django se encarga de que cada test sea aislado: crea datos y luego los borra automáticamente.

Podemos usar el método especial setUp() para preparar los datos previos:

from django.test import TestCase
from django.urls import reverse

from .models import Users

class UsersTest(TestCase):
    def setUp(self):
        # Creamos un usuario en la base de datos para luego modificarlo
        self.user = Users.objects.create(name="John", email="johndoe@mail.com")

    def test_update_user(self):
        # Simulamos una actualización del usuario (ejemplo ficticio)
        response = self.client.post(reverse("users:create", kwargs={"name": "Bob"}))  

        # Verificamos que el cambio se refleje en la base
        updated_user = Users.objects.get(pk=self.user.id)
        self.assertEqual(updated_user.name, "Bob")

Cada test corre en su propia transacción. Así, si modificas algo, Django lo "deshace" al final, y el siguiente test empieza limpio.


Cargar muchos datos con fixtures

Cuando necesitas muchos datos para la prueba, lo mejor es usar una fixture. Es un archivo con datos de prueba, usualmente en formato JSON.

Cómo crear una fixture

Primero, crea registros reales en tu base de datos. Luego corre:

uv run manage.py dumpdata > users.json

Guarda ese archivo en un directorio llamado fixtures dentro de la app. Ejemplo de contenido:

[
  {
    "model": "users.user",
    "pk": 1,
    "fields": {
      "password": "superpass",
      "email": "johndoe@mail.com",
      "name": "John"
    }
  },
  {
    "model": "users.user",
    "pk": 2,
    "fields": {
      "password": "password123",
      "name": "Alice",
      "email": "alicesmith@email.com"
    }
  }
]

Usar la fixture en un test

from django.test import TestCase
from django.urls import reverse
from .models import Users

class UsersTest(TestCase):
    fixtures = ['users.json']  # Django la carga automáticamente antes de cada test

    def test_update_user(self):
        user = Users.objects.get(pk=1)

        # Simular actualización
        response = self.client.post(reverse("users:create", kwargs={"name": "Bob"}))

        updated_user = Users.objects.get(pk=1)
        self.assertEqual(updated_user.name, "Bob")

Así Django ya tiene disponibles los datos antes de correr setUp().


¿Por qué son tan útiles estas pruebas?

Fíjate que en ningún momento dependimos del código interno de la app. Solo probamos si los resultados son correctos. Esa es la ventaja de las pruebas de integración: si el API de la app devuelve lo esperado, todo va bien, incluso si internamente cambias detalles del código.


Resumen

  • Las pruebas de integración simulan el comportamiento real del usuario consultando rutas del proyecto.
  • Usamos el client de Django para hacer solicitudes simuladas como GET y POST sin activar un servidor real.
  • assertEqual() y assertIn() permiten verificar que las respuestas sean correctas.
  • setUp() prepara datos antes de cada test y garantiza que cada prueba sea independiente.
  • Las fixtures permiten cargar varios datos desde archivos JSON antes de cada test.

Para acceder completo a curso necesitas un plan básico

El plan básico te dará acceso completo a todos los cursos, ejercicios y lecciones de Códica, proyectos y acceso de por vida a la teoría de las lecciones completadas. La suscripción se puede cancelar en cualquier momento.

Obtener acceso
130
cursos
1000
ejercicios
2000+
horas de teoría
3200
test

Obtén acceso

Cursos de programación para principiantes y desarrolladores experimentados. Comienza tu aprendizaje de forma gratuita

  • 130 cursos, 2000+ horas de teoría
  • 1000 ejercicios prácticos en el navegador
  • 360 000 estudiantes
Al enviar el formulario, aceptas el «Política de privacidad» y los términos de la «Oferta», y también aceptas los «Términos y condiciones de uso»

Nuestros graduados trabajan en empresas como:

Bookmate
Health Samurai
Dualboot
ABBYY