El Client de test de Django
self.client es un cliente HTTP simulado disponible en todos los TestCase de Django. Permite hacer peticiones GET, POST, PUT, DELETE, etc. sin necesitar un servidor real:
from django.test import TestCase
from django.urls import reverse
from django.contrib.auth import get_user_model
from .models import Producto, Categoria
User = get_user_model()
class ProductoListViewTest(TestCase):
@classmethod
def setUpTestData(cls):
cls.categoria = Categoria.objects.create(nombre='Test', slug='test')
cls.producto = Producto.objects.create(
nombre='Laptop Test',
precio=999.99,
categoria=cls.categoria,
activo=True
)
cls.url = reverse('catalogo:producto-list')
def test_lista_accesible_sin_autenticacion(self):
"""El listado de productos debe ser público."""
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
def test_lista_usa_template_correcto(self):
response = self.client.get(self.url)
self.assertTemplateUsed(response, 'catalogo/producto_list.html')
def test_lista_contiene_producto(self):
response = self.client.get(self.url)
self.assertContains(response, 'Laptop Test')
def test_lista_no_muestra_inactivos(self):
producto_inactivo = Producto.objects.create(
nombre='Producto Inactivo',
precio=10.00,
categoria=self.categoria,
activo=False
)
response = self.client.get(self.url)
self.assertNotContains(response, 'Producto Inactivo')
def test_paginacion(self):
# Crear muchos productos para activar la paginación
for i in range(15):
Producto.objects.create(
nombre=f'Producto {i}',
precio=10.00,
categoria=self.categoria
)
response = self.client.get(self.url)
self.assertIn('is_paginated', response.context)

Tests de vistas autenticadas
class CrearProductoViewTest(TestCase):
@classmethod
def setUpTestData(cls):
cls.categoria = Categoria.objects.create(nombre='Test', slug='test')
cls.usuario = User.objects.create_user(
username='testuser',
password='testpass123'
)
cls.usuario_admin = User.objects.create_user(
username='admin',
password='admin123',
is_staff=True
)
cls.url = reverse('catalogo:producto-create')
def test_redirige_si_no_autenticado(self):
response = self.client.get(self.url)
self.assertRedirects(response, f'/login/?next={self.url}')
def test_accesible_para_usuario_autenticado(self):
self.client.login(username='testuser', password='testpass123')
response = self.client.get(self.url)
self.assertEqual(response.status_code, 200)
def test_crear_producto_post_valido(self):
self.client.force_login(self.usuario_admin)
datos = {
'nombre': 'Nuevo Producto',
'precio': '49.99',
'categoria': self.categoria.pk,
}
response = self.client.post(self.url, data=datos)
self.assertEqual(response.status_code, 302) # Redirección tras éxito
self.assertTrue(Producto.objects.filter(nombre='Nuevo Producto').exists())
def test_crear_producto_post_invalido(self):
self.client.force_login(self.usuario_admin)
datos = {'nombre': '', 'precio': '-1'} # Datos inválidos
response = self.client.post(self.url, data=datos)
self.assertEqual(response.status_code, 200) # Re-renderiza el formulario
self.assertFormError(response, 'form', 'nombre', 'Este campo es obligatorio.')
Assertions principales del Client
# Verificar status code
self.assertEqual(response.status_code, 200)
# Verificar contenido en la respuesta
self.assertContains(response, 'texto esperado')
self.assertContains(response, 'texto', count=3) # Aparece exactamente 3 veces
self.assertNotContains(response, 'texto no esperado')
# Verificar redirección
self.assertRedirects(response, '/productos/')
self.assertRedirects(response, '/productos/', status_code=302, target_status_code=200)
# Verificar plantillas usadas
self.assertTemplateUsed(response, 'catalogo/producto_list.html')
self.assertTemplateNotUsed(response, 'catalogo/error.html')
# Verificar contexto de la plantilla
self.assertIn('productos', response.context)
self.assertEqual(len(response.context['productos']), 5)
# Verificar errores de formulario
self.assertFormError(response, 'form', 'nombre', 'Este campo es obligatorio.')
Testing de APIs con APIClient (DRF)
from rest_framework.test import APIClient, APITestCase
from rest_framework import status
from django.urls import reverse
class ProductoAPITest(APITestCase):
@classmethod
def setUpTestData(cls):
cls.categoria = Categoria.objects.create(nombre='Test', slug='test')
cls.usuario = User.objects.create_user(username='api_user', password='pass123')
cls.url_lista = reverse('producto-list') # Router de DRF
def setUp(self):
self.client = APIClient()
def test_lista_sin_autenticacion(self):
response = self.client.get(self.url_lista)
self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_crear_producto_requiere_autenticacion(self):
response = self.client.post(self.url_lista, {'nombre': 'Test'})
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
def test_crear_producto_autenticado(self):
self.client.force_authenticate(user=self.usuario)
datos = {
'nombre': 'API Producto',
'precio': '29.99',
'categoria': self.categoria.pk,
}
response = self.client.post(self.url_lista, data=datos)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(response.data['nombre'], 'API Producto')
def test_obtener_token_jwt(self):
url = reverse('token_obtain_pair')
response = self.client.post(url, {
'username': 'api_user',
'password': 'pass123'
})
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIn('access', response.data)
self.assertIn('refresh', response.data)
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Django es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de Django
Explora más contenido relacionado con Django y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
Usar self.client para simular peticiones GET y POST a las vistas. Verificar el status code, el contenido y las redirecciones de las respuestas. Usar assertContains, assertRedirects y assertTemplateUsed. Autenticar usuarios en tests con self.client.login() y self.client.force_login(). Testear APIs REST con el APIClient de Django REST Framework.