Saltar al contenido
Pantalla de terminal con marcas verdes de pruebas aprobadas junto a un cuaderno de apuntes en un escritorio
Aprender IA

Testing con pytest: escribe tu primera prueba automatizada en Python

Una prueba automatizada es una afirmación verificable: dado este dato, espero esta salida. Con pytest escribís la primera en diez minutos y ganás una red de seguridad que avisa en segundos cuando un cambio rompe lo que funcionaba. Toda prueba sigue el patrón preparar, ejecutar y verificar.

Por · Equipo de contenido y revisiónPublicado: 7 min de lectura

Puntos clave

Los puntos que más importan

  • Toda prueba sigue el patrón preparar, ejecutar y verificar.
  • Los errores viven en los límites: probá 9999.99, 10000, 49999 y 50000, no solo valores cómodos.
  • Usá parametrize para no repetir y approx para comparar decimales.
  • Cada error real que encuentres deja una prueba fija: así no vuelve.
  • Las pruebas no detectan requisitos mal entendidos, problemas de rendimiento ni fallos de seguridad.

Una prueba automatizada es un programa pequeño que verifica que otro programa hace lo que promete. La escribes una vez y la ejecutas cada vez que cambias algo: si el resultado esperado deja de cumplirse, la prueba falla y te avisa en segundos, en lugar de que el error aparezca en producción un viernes por la noche. Con pytest, escribir tu primera prueba lleva menos de diez minutos y no necesitas aprender ningún marco teórico complicado.

Esta guía asume que ya escribiste funciones en Python y quieres dar el paso que separa el código de práctica del código profesional. Vamos a instalar la herramienta, escribir una prueba real, entender los casos borde y decidir qué vale la pena testear y qué no.

Qué es una prueba automatizada (en una frase)

Una prueba es una afirmación verificable: dado este dato de entrada, espero exactamente esta salida. Si la afirmación se cumple, la prueba pasa; si no, falla.

El patrón universal se llama arrange, act, assert (preparar, ejecutar, verificar):

  1. Preparar los datos y el entorno (crear la función, el archivo o el cliente).
  2. Ejecutar la operación que quieres probar.
  3. Verificar el resultado con una comparación.

Todo lo demás son variantes de ese patrón. Cuando una prueba se vuelve ilegible es porque mezcló los tres pasos.

Instalación y tu primer archivo de test

Crea un entorno virtual, instala pytest y arma esta estructura mínima:

proyecto/
├── descuentos.py
└── tests/
    └── test_descuentos.py

El código que queremos probar:

# descuentos.py
def aplicar_descuento(precio, porcentaje):
    if precio < 0:
        raise ValueError("El precio no puede ser negativo")
    if not 0 <= porcentaje <= 100:
        raise ValueError("El porcentaje debe estar entre 0 y 100")
    return round(precio * (1 - porcentaje / 100), 2)

La primera prueba:

# tests/test_descuentos.py
import pytest
from descuentos import aplicar_descuento

def test_aplica_diez_por_ciento():
    assert aplicar_descuento(1000, 10) == 900.0

def test_precio_negativo_falla():
    with pytest.raises(ValueError):
        aplicar_descuento(-50, 10)

Se ejecuta con pytest desde la raíz del proyecto. La salida te muestra un punto por prueba aprobada y una F por cada fallo. Nada más: sin configuración, sin clases, sin archivos obligatorios.

Ejemplo trabajado: probar una función que calcula comisiones

Vamos a un caso más realista. Un vendedor cobra una comisión escalonada y necesitamos estar seguros de que el cálculo no se rompe en los límites.

# comisiones.py
def calcular_comision(monto):
    if monto < 0:
        raise ValueError("El monto no puede ser negativo")
    if monto < 10000:
        return round(monto * 0.05, 2)
    if monto < 50000:
        return round(monto * 0.08, 2)
    return round(monto * 0.12, 2)

Estas son las pruebas que un equipo experimentado escribiría primero:

import pytest
from comisiones import calcular_comision

@pytest.mark.parametrize("monto, esperado", [
    (0, 0.0),            # mínimo
    (9999.99, 499.9995), # justo antes del primer corte
    (10000, 800.0),      # límite exacto del primer cambio
    (49999, 3999.92),    # justo antes del segundo corte
    (50000, 6000.0),     # límite exacto del segundo cambio
])
def test_tramos(monto, esperado):
    assert calcular_comision(monto) == pytest.approx(esperado, rel=1e-9)

def test_monto_negativo():
    with pytest.raises(ValueError):
        calcular_comision(-1)

Tres cosas hacen valiosa esta prueba: usa parametrize para no repetir código, prueba los límites exactos (9999.99, 10000, 49999, 50000) y compara números decimales con approx en lugar de == para no pelear con la aritmética de punto flotante.

CasoQué verificaPor qué importa
0El tramo más bajo acepta ceroEvita un None inesperado
9999.99Un centavo antes del corteLos errores viven en los límites
10000El corte exactoDefine qué tramo gana el empate
49999Segundo límiteEscalones anidados
50000Tramo más altoEl porcentaje final
-1Entrada inválidaFalla rápido y con mensaje claro

Casos borde: donde se rompe el código real

Los casos borde no son un extra: son el motivo por el que escribes pruebas. Antes de dar una función por terminada, pregúntate:

  • ¿Qué pasa con cero y con negativos?
  • ¿Qué pasa con el primer y el último elemento de una lista?
  • ¿Qué pasa si el texto tiene tildes, mayúsculas o espacios de más?
  • ¿Qué pasa si el archivo está vacío o no existe?
  • ¿Qué pasa si el monto tiene más de dos decimales?

Cada respuesta que no te guste es un caso de prueba que hay que escribir.

Fixtures: preparar el entorno sin repetirte

Cuando varias pruebas necesitan el mismo dato, pytest ofrece fixtures: funciones que preparan algo y lo entregan a la prueba que lo pida.

import pytest
from pathlib import Path

@pytest.fixture
def carpeta_de_entrada(tmp_path):
    for nombre in ("ventas_enero.csv", "ventas_febrero.csv"):
        (tmp_path / nombre).write_text("fecha,monto\n2026-01-05,1500\n", encoding="utf-8")
    return tmp_path

def test_lee_todos_los_archivos(carpeta_de_entrada: Path):
    archivos = list(carpeta_de_entrada.glob("ventas_*.csv"))
    assert len(archivos) == 2

tmp_path es una carpeta temporal que pytest limpia sola. Esto te permite probar código que escribe archivos sin ensuciar tu proyecto.

Cómo integrarlo a tu flujo de trabajo

Una prueba que no se ejecuta no sirve. El orden recomendado para incorporarlas sin fricción:

  1. Ejecuta pytest antes de cada commit. Si tarda más de diez segundos, ejecuta solo los archivos que tocaste.
  2. Agrega una prueba por cada error real que encuentres. Empieza con el error, escribe la prueba que lo reproduce, arregla el código y deja la prueba fija.
  3. Mide cobertura con criterio. Un 100% de cobertura en un proyecto mediocre no significa nada; un 60% en los módulos que tocan dinero sí.
  4. Automatiza en un servidor. Cuando el proyecto tenga más de una persona, las pruebas deben correr solas con cada cambio en el repositorio.

Qué no vale la pena testear

Escribir pruebas también cuesta tiempo y mantenimiento. Tiene sentido no testear:

  • Código de terceros. No verifiques que el framework funciona; verifica cómo lo usas.
  • Detalles de implementación. Si una prueba se rompe cada vez que renombras una variable interna, está mal escrita.
  • Interfaces cambiantes. Probar el texto exacto de una pantalla que rediseñan cada mes genera ruido.
  • Scripts de un solo uso. Un script que se ejecuta una vez y se descarta no necesita batería de pruebas.

La regla razonable: prueba la lógica de negocio, los cálculos, las validaciones y cualquier cosa que se ejecute muchas veces o que toque dinero, salud o datos de personas.

Limitaciones: qué no te dicen las pruebas

Las pruebas verifican lo que tú pensaste, con los datos que tú elegiste. No te avisan de:

  • Un requisito mal entendido. Si implementaste la regla equivocada, la prueba confirma el error.
  • Datos de producción raros. Un apellido con caracteres especiales, un archivo de 800 MB, una fecha del año 1900.
  • Problemas de rendimiento. Una función puede pasar todas las pruebas y tardar veinte minutos en producción.
  • Fallos de infraestructura. Caídas de red, límites de memoria, permisos.
  • Seguridad. Que el código funcione no implica que sea seguro.

Para esas cosas necesitas monitoreo, pruebas de carga, revisión de código y, sobre todo, personas mirando resultados reales.

Preguntas frecuentes

¿Cuántas pruebas debe tener un proyecto chico? Suficientes para cubrir la lógica central y los límites. En una utilidad de 200 líneas, entre 5 y 20 pruebas es un número razonable.

¿pytest o unittest? pytest es la opción práctica hoy: menos código repetido, mejor salida de errores y una comunidad enorme. unittest sigue existiendo en proyectos antiguos.

¿Necesito aprender mocking? Cuando tu código hable con servicios externos (una API, una base de datos, un envío de correo). Empieza probando funciones puras y aprende mocking cuando aparezca la primera dependencia externa.

¿Puedo testear código que ya escribí sin pruebas? Sí, y es un buen ejercicio: elige el módulo más usado, escribe pruebas del comportamiento actual y solo después empieza a refactorizar. Ese paso previo se llama prueba de caracterización.

¿Las pruebas reemplazan a las personas de QA? No. Automatizan lo repetitivo y liberan tiempo humano para explorar lo que nadie anticipó.

¿Qué hago si una prueba falla de forma intermitente? Búscala como prioridad: casi siempre indica que hay una dependencia de tiempo, orden o estado compartido. Una prueba inestable contamina la confianza en todo el conjunto.

Siguiente paso

Escribir tu primera prueba es el cambio de hábito más rentable para quien programa. Si quieres reforzar la base de Python antes de avanzar, revisa el temario de Python para principiantes; si tu interés está en construir y publicar, la categoría Proyectos y casos reales reúne ejemplos aplicados. Y si prefieres una ruta guiada con ejercicios revisados, mira los cursos de Cursalo y la biblioteca de prompts para practicar con asistencia.

Fuentes

Referencias externas

  1. pytest en PyPIPython Package Index
  2. unittest: marco de pruebas de la biblioteca estándarPython Software Foundation

Siguiente paso

Domina la IA con Cursalo

Crea tu cuenta y avanza con rutas estructuradas, proyectos reales, libros y biblioteca de prompts.

02 / LLEVAR A LA PRÁCTICA

Después de leer

Convierte una idea útil en una habilidad repetible.

Elige una ruta breve, aplícala a una tarea real y termina con algo que puedas revisar, usar o compartir.