14. Ejecutar una prueba, un archivo, una carpeta o toda la suite

14.1 Objetivo del tema

En proyectos reales no siempre queremos ejecutar todas las pruebas. Mientras corregimos un error, suele ser más rápido ejecutar una prueba específica. Antes de terminar, conviene ejecutar toda la suite.

En este tema veremos cómo ejecutar todas las pruebas, una carpeta, un archivo, una clase y una función puntual usando pytest.

Idea clave: pytest permite ejecutar desde lo más general hasta lo más específico usando rutas y el separador ::.

14.2 Crear una carpeta de práctica

Crea un proyecto nuevo:

mkdir pytest-ejecucion-demo
cd pytest-ejecucion-demo

Si pytest no está instalado en el entorno activo, instálalo:

python -m pip install pytest

14.3 Crear la estructura del proyecto

Crea estas carpetas:

mkdir app
mkdir tests
mkdir tests\unit
mkdir tests\integration

En Linux o macOS:

mkdir -p app tests/unit tests/integration

14.4 Crear el código principal

Dentro de app, crea calculadora.py:

def sumar(a, b):
    return a + b


def restar(a, b):
    return a - b


def dividir(a, b):
    if b == 0:
        raise ValueError("No se puede dividir por cero")
    return a / b

Ahora crea app\usuarios.py:

def normalizar_nombre(nombre):
    return nombre.strip().title()


def es_mayor_de_edad(edad):
    return edad >= 18

14.5 Crear pruebas unitarias de calculadora

Dentro de tests\unit, crea test_calculadora.py:

import pytest

from app.calculadora import dividir, restar, sumar


def test_sumar():
    assert sumar(2, 3) == 5


def test_restar():
    assert restar(10, 4) == 6


def test_dividir():
    assert dividir(10, 2) == 5


def test_dividir_por_cero_lanza_error():
    with pytest.raises(ValueError):
        dividir(10, 0)

14.6 Crear pruebas unitarias de usuarios

Dentro de tests\unit, crea test_usuarios.py:

from app.usuarios import es_mayor_de_edad, normalizar_nombre


def test_normalizar_nombre():
    assert normalizar_nombre("  ana  ") == "Ana"


def test_edad_18_es_mayor_de_edad():
    assert es_mayor_de_edad(18) is True


def test_edad_17_no_es_mayor_de_edad():
    assert es_mayor_de_edad(17) is False

14.7 Crear una prueba de integración simple

Dentro de tests\integration, crea test_flujo_usuario.py:

from app.calculadora import sumar
from app.usuarios import normalizar_nombre


def test_flujo_registro_con_puntaje():
    nombre = normalizar_nombre("  ana  ")
    puntaje = sumar(40, 2)

    assert nombre == "Ana"
    assert puntaje == 42

La carpeta integration representa pruebas que combinan más de una parte del código.

14.8 Ejecutar toda la suite

Desde la raíz del proyecto, ejecuta:

python -m pytest

La salida esperada será similar a:

collected 8 items

tests/integration/test_flujo_usuario.py .                       [ 12%]
tests/unit/test_calculadora.py ....                             [ 62%]
tests/unit/test_usuarios.py ...                                 [100%]

8 passed in 0.03s

14.9 Ejecutar una carpeta

Para ejecutar solo las pruebas unitarias:

python -m pytest tests\unit

En Linux o macOS:

python -m pytest tests/unit

Para ejecutar solo las pruebas de integración:

python -m pytest tests\integration

14.10 Ejecutar un archivo

Para ejecutar solamente las pruebas de calculadora:

python -m pytest tests\unit\test_calculadora.py

En Linux o macOS:

python -m pytest tests/unit/test_calculadora.py

Esto ejecuta todas las funciones de prueba dentro de ese archivo.

14.11 Ejecutar una prueba específica

Para ejecutar una sola función de prueba, usa :: después de la ruta del archivo:

python -m pytest tests\unit\test_calculadora.py::test_dividir_por_cero_lanza_error

Este comando es muy útil mientras corriges una regla puntual.

14.12 Ejecutar con salida detallada

La opción -v muestra el nombre de cada prueba:

python -m pytest -v

También puede combinarse con una ruta específica:

python -m pytest tests\unit\test_usuarios.py -v

14.13 Ejecutar una prueba con salida detallada

Podemos combinar ruta, nombre de prueba y -v:

python -m pytest tests\unit\test_usuarios.py::test_edad_18_es_mayor_de_edad -v

La salida indicará explícitamente esa prueba y su resultado.

14.14 Ejecutar por nombre con -k

La opción -k permite seleccionar pruebas cuyo nombre contiene una expresión:

python -m pytest -k edad

Este comando ejecuta pruebas con edad en el nombre, como test_edad_18_es_mayor_de_edad y test_edad_17_no_es_mayor_de_edad.

14.15 Excluir por nombre con -k

También podemos excluir coincidencias:

python -m pytest -k "not edad"

Esto ejecuta las pruebas cuyo nombre no coincide con edad.

14.16 Ejecutar y detenerse en la primera falla

La opción -x detiene la suite cuando aparece la primera falla:

python -m pytest -x

Es útil cuando una falla inicial puede provocar muchas fallas derivadas.

14.17 Ejecutar solo fallas recientes

Después de una ejecución con fallas, pytest puede repetir solo las que fallaron con:

python -m pytest --lf

--lf significa last failed. Es práctico durante ciclos de corrección.

14.18 Tabla de comandos frecuentes

Objetivo Comando
Toda la suite python -m pytest
Una carpeta python -m pytest tests\unit
Un archivo python -m pytest tests\unit\test_calculadora.py
Una prueba python -m pytest tests\unit\test_calculadora.py::test_sumar
Por nombre python -m pytest -k edad
Detener en primera falla python -m pytest -x

14.19 Estructura final del proyecto

pytest-ejecucion-demo/
|-- app/
|   |-- calculadora.py
|   `-- usuarios.py
`-- tests/
    |-- integration/
    |   `-- test_flujo_usuario.py
    `-- unit/
        |-- test_calculadora.py
        `-- test_usuarios.py

Esta organización permite ejecutar grupos completos de pruebas por carpeta.

14.20 Errores frecuentes

  • Ejecutar desde una carpeta incorrecta: pueden fallar importaciones como from app....
  • Escribir mal el nombre después de ::: pytest no encontrará esa prueba.
  • Confundir barras de Windows y Linux: en Windows se usa \, en Linux y macOS se usa /.
  • Usar -k con una palabra demasiado amplia: puede ejecutar más pruebas de las esperadas.
  • No ejecutar toda la suite al final: una prueba puntual puede pasar mientras otra parte del proyecto quedó rota.

14.21 Comandos usados en este tema

mkdir pytest-ejecucion-demo
cd pytest-ejecucion-demo
python -m pip install pytest
mkdir app
mkdir tests
mkdir tests\unit
mkdir tests\integration
python -m pytest
python -m pytest tests\unit
python -m pytest tests\unit\test_calculadora.py
python -m pytest tests\unit\test_calculadora.py::test_dividir_por_cero_lanza_error
python -m pytest -v
python -m pytest -k edad
python -m pytest -x
python -m pytest --lf

14.22 Qué debes recordar de este tema

  • python -m pytest ejecuta toda la suite descubierta.
  • Pasar una carpeta limita la ejecución a esa carpeta.
  • Pasar un archivo ejecuta solo las pruebas de ese archivo.
  • :: permite apuntar a una prueba específica.
  • -k selecciona pruebas por nombre.
  • Después de trabajar con pruebas puntuales, conviene ejecutar toda la suite.

14.23 Conclusión

En este tema aprendimos a ejecutar pruebas con distintos niveles de precisión: toda la suite, una carpeta, un archivo o una prueba puntual. Esto permite trabajar rápido durante el desarrollo y verificar todo antes de cerrar un cambio.

En el próximo tema veremos opciones útiles de pytest desde la terminal para controlar mejor la salida y el comportamiento de la ejecución.