Saltar a contenido

Testing

El Sistema A3 utiliza pytest para testing. Esta guía explica cómo escribir y ejecutar tests.

Setup

pip install pytest pytest-django model-bakery

Ejecutar Tests

# Todos los tests
pytest

# Tests de una app
pytest inventario/tests.py

# Un test específico
pytest inventario/tests.py::test_crear_casa

# Con cobertura
pytest --cov=inventario

# Verbose
pytest -v

Estructura

inventario/
├── models.py
├── views.py
└── tests.py  # o tests/
    ├── __init__.py
    ├── test_models.py
    ├── test_views.py
    └── test_api.py

Escribir Tests

Test de Modelo

import pytest
from model_bakery import baker
from inventario.models import Casa

@pytest.mark.django_db
class TestCasaModel:
    def test_crear_casa(self):
        casa = baker.make(Casa, clave='MTY-001')
        assert casa.clave == 'MTY-001'

    def test_clave_unique(self):
        baker.make(Casa, clave='MTY-001')
        with pytest.raises(Exception):
            baker.make(Casa, clave='MTY-001')

Test de Vista

from django.test import Client
from django.contrib.auth.models import User

@pytest.mark.django_db
def test_listar_casas():
    client = Client()
    user = User.objects.create_user('test', 'test@test.com', 'pass')
    client.login(username='test', password='pass')

    response = client.get('/inventario/casas/')
    assert response.status_code == 200

Test de API

from rest_framework.test import APIClient

@pytest.mark.django_db
def test_api_casas():
    client = APIClient()
    client.force_authenticate(user=usuario)

    response = client.get('/api/inventario/casas/')
    assert response.status_code == 200
    assert 'results' in response.json()

Fixtures

# conftest.py
import pytest
from django.contrib.auth.models import User

@pytest.fixture
def usuario():
    return User.objects.create_user('test', 'test@test.com', 'pass')

@pytest.fixture
def casa(usuario):
    return Casa.objects.create(
        clave='MTY-001',
        proyecto='Hacienda',
        usuario_creacion=usuario
    )

# En tests
def test_con_fixtures(usuario, casa):
    assert casa.usuario_creacion == usuario

Mocking

from unittest.mock import patch, Mock

@patch('services.sap_service.SAPService.crear_vivienda')
def test_crear_casa_con_sap(mock_sap):
    mock_sap.return_value = {'Id': 123}

    casa = crear_casa_con_sincronizacion(data)

    assert mock_sap.called
    assert casa.id_sap == 123

Model Bakery

from model_bakery import baker

# Crear instancia simple
casa = baker.make(Casa)

# Con valores específicos
casa = baker.make(Casa, clave='MTY-001', plaza='MONTERREY')

# Crear múltiples
casas = baker.make(Casa, _quantity=10)

# Preparar sin guardar
casa = baker.prepare(Casa)

Coverage

# Ejecutar con coverage
pytest --cov=. --cov-report=html

# Ver reporte
open htmlcov/index.html

CI Integration

Tests se ejecutan automáticamente en pushes a GitHub (si existe workflow).

Best Practices

  1. Un test, un assertion: Enfócate en una cosa
  2. Tests independientes: No depender de orden de ejecución
  3. Nombres descriptivos: test_crear_casa_sin_precio_falla
  4. Arrange-Act-Assert: Estructura clara
  5. Mock dependencias externas: SAP API, S3, etc.
def test_ejemplo():
    # Arrange (preparar)
    casa = baker.make(Casa)

    # Act (actuar)
    resultado = procesar_casa(casa)

    # Assert (verificar)
    assert resultado.success

Testing Frontend

Actualmente no hay tests automáticos de JavaScript. Se recomienda agregar:

  • Jest para unit tests
  • Cypress para E2E tests

Para más info sobre pytest-django: pytest-django.readthedocs.io