19. Organización de archivos y suites de pruebas

19.1 Introducción

A medida que un proyecto crece, también crece la cantidad de pruebas. Si los archivos de prueba no están bien organizados, la suite se vuelve difícil de navegar, ejecutar y mantener.

Una buena organización permite encontrar rápidamente las pruebas de una unidad, entender qué parte del sistema cubren y ejecutar grupos de pruebas según la necesidad.

En este tema veremos criterios generales para organizar archivos y suites de pruebas unitarias, sin depender de un lenguaje específico.

19.2 Qué es una suite de pruebas

Una suite de pruebas es un conjunto de pruebas que se ejecutan juntas. Puede incluir todas las pruebas del proyecto o solo un subconjunto.

Ejemplos de suites:

  • Todas las pruebas unitarias del proyecto.
  • Las pruebas de un módulo específico.
  • Las pruebas de una clase o función concreta.
  • Las pruebas rápidas que se ejecutan durante el desarrollo.
  • Las pruebas que se ejecutan antes de publicar una versión.

En pruebas unitarias, buscamos que la suite sea rápida, clara y confiable.

19.3 Objetivos de una buena organización

Una estructura de pruebas debería ayudar a:

  • Encontrar pruebas fácilmente.
  • Relacionar cada prueba con la unidad que verifica.
  • Evitar archivos gigantes y difíciles de mantener.
  • Ejecutar subconjuntos de pruebas cuando sea necesario.
  • Facilitar que nuevas personas entiendan el proyecto.
  • Mantener separadas pruebas unitarias, de integración y end-to-end.
La organización no es solo orden estético: reduce fricción cada vez que alguien agrega, ejecuta o depura una prueba.

19.4 Ubicar pruebas junto al código o en carpeta separada

Hay dos estilos comunes para ubicar pruebas:

Estilo Descripción Ventaja
Pruebas junto al código El archivo de prueba se coloca cerca del archivo probado. Es fácil ver código y prueba juntos.
Carpeta separada de pruebas Las pruebas viven en una carpeta como tests o test. Se separa claramente código productivo y código de prueba.

No hay una única respuesta correcta. Lo importante es que el proyecto sea consistente.

19.5 Ejemplo de carpeta separada

Una estructura típica puede ser:

proyecto/
  src/
    calculadora.py
    descuentos.py
  tests/
    test_calculadora.py
    test_descuentos.py

El archivo test_descuentos.py contiene pruebas para descuentos.py. La relación es fácil de deducir por el nombre.

19.6 Ejemplo de pruebas junto al código

Otro estilo es colocar la prueba junto a la unidad:

proyecto/
  src/
    descuentos.py
    descuentos_test.py
    calculadora.py
    calculadora_test.py

Este estilo se usa bastante en algunos ecosistemas. Permite localizar la prueba cerca del archivo probado, aunque mezcla archivos de producción y prueba en la misma carpeta.

19.7 Convenciones de nombres

Los frameworks suelen detectar pruebas por convenciones de nombres. Algunos ejemplos comunes:

  • Python: archivos como test_descuentos.py o descuentos_test.py.
  • Java: clases como CalculadoraTest.
  • JavaScript: archivos como descuentos.test.js o descuentos.spec.js.

Más allá del lenguaje, conviene que el nombre del archivo indique claramente qué unidad o módulo se prueba.

19.8 Un archivo de prueba por unidad o módulo

Una práctica habitual es tener un archivo de prueba por módulo, clase o unidad importante.

src/
  carrito.py
  pedido.py
  cliente.py
tests/
  test_carrito.py
  test_pedido.py
  test_cliente.py

Esta correspondencia facilita encontrar pruebas. Si queremos revisar el comportamiento de pedido.py, sabemos dónde buscar.

19.9 Evitar archivos de prueba gigantes

Un archivo de prueba con cientos o miles de líneas puede volverse difícil de mantener. Si un módulo tiene muchas responsabilidades y muchas pruebas, quizá convenga dividirlo.

Posibles divisiones:

  • Por clase.
  • Por función principal.
  • Por grupo de reglas.
  • Por comportamiento relacionado.

Si las pruebas de una unidad crecen demasiado, también puede ser señal de que la unidad productiva tiene demasiadas responsabilidades.

19.10 Agrupar pruebas relacionadas

Dentro de un archivo, conviene agrupar pruebas relacionadas. Por ejemplo, las pruebas de descuentos pueden dividirse por tipo de cliente o por reglas de monto.

def test_cliente_comun_no_tiene_descuento():
    assert obtener_descuento("comun") == 0


def test_cliente_vip_tiene_descuento_15():
    assert obtener_descuento("vip") == 15


def test_cliente_empleado_tiene_descuento_20():
    assert obtener_descuento("empleado") == 20

La cercanía entre estas pruebas ayuda a leer la regla completa.

19.11 Separar unitarias de integración

Es importante no mezclar pruebas unitarias con pruebas de integración en la misma suite sin distinguirlas. Las unitarias deberían ser rápidas y con pocas dependencias; las de integración pueden necesitar base de datos, red o servicios.

Una estructura posible:

tests/
  unit/
    test_descuentos.py
    test_validaciones.py
  integration/
    test_repositorio_usuarios.py
    test_api_pedidos.py

Esta separación permite ejecutar solo unitarias durante el desarrollo y dejar integración para momentos específicos.

19.12 Separar pruebas lentas

Si algunas pruebas tardan más, conviene identificarlas. Una suite unitaria lenta se ejecuta menos y pierde valor como retroalimentación rápida.

Las pruebas lentas suelen indicar que:

  • Dependen de recursos externos.
  • Procesan demasiados datos.
  • Están probando más que una unidad.
  • Necesitan una preparación excesiva.

Si una prueba unitaria se vuelve lenta, conviene revisar si realmente es unitaria.

19.13 Orden de las pruebas

Las pruebas unitarias no deberían depender del orden de ejecución. Cada prueba debe preparar sus propios datos y poder ejecutarse de manera independiente.

Ejemplo riesgoso:

usuarios = []


def test_agregar_usuario():
    usuarios.append("Ana")
    assert len(usuarios) == 1


def test_lista_tiene_usuario():
    assert "Ana" in usuarios

La segunda prueba depende de que la primera se haya ejecutado antes. Esto rompe la independencia y puede generar fallas difíciles de entender.

19.14 Suites pequeñas durante el desarrollo

Durante el desarrollo, muchas veces queremos ejecutar solo las pruebas relacionadas con el cambio actual. Una buena organización facilita esto.

Ejemplos de ejecución selectiva:

  • Solo las pruebas de un archivo.
  • Solo las pruebas de una clase.
  • Solo las pruebas cuyo nombre contiene cierta palabra.
  • Solo las pruebas unitarias rápidas.

La posibilidad de ejecutar subconjuntos acelera el ciclo de trabajo.

19.15 Nombres de carpetas claros

Los nombres de carpetas deben comunicar el tipo de prueba o el área del sistema.

tests/
  unit/
  integration/
  e2e/

Otra opción es organizar por módulo:

tests/
  pedidos/
  usuarios/
  pagos/

La elección depende del tamaño del proyecto, pero conviene evitar estructuras ambiguas como misc, varios o pruebas2.

19.16 Archivos auxiliares de prueba

Las pruebas pueden necesitar helpers, datos de ejemplo o pequeñas fábricas de objetos. Conviene ubicarlos de forma clara.

tests/
  unit/
    test_descuentos.py
    test_carrito.py
  helpers/
    builders.py
    datos.py

Los helpers deben seguir siendo simples. Si crecen demasiado, pueden convertirse en otra fuente de complejidad.

19.17 Evitar mezclar pruebas con datos grandes

Para pruebas unitarias, normalmente no hace falta cargar archivos enormes de datos. Los datos pequeños y explícitos suelen ser mejores.

Si una prueba necesita un archivo grande, puede ser señal de que:

  • Está probando integración o procesamiento completo.
  • La unidad no está bien separada.
  • Se podría usar un dato mínimo representativo.

Los datos grandes pueden ser útiles en otros tipos de pruebas, pero no deberían ser la norma en pruebas unitarias.

19.18 Tabla de decisiones

Situación Organización recomendada
Proyecto pequeño Carpeta tests con archivos por módulo.
Proyecto con varios tipos de prueba Separar unit, integration y e2e.
Módulo con muchas reglas Dividir pruebas por comportamiento o clase.
Preparación repetida Crear helpers simples y visibles.
Pruebas lentas mezcladas con unitarias Separarlas o marcarlas para ejecución aparte.

19.19 Lista de comprobación

Al organizar pruebas, revisa:

  • ¿Es fácil encontrar la prueba de una unidad?
  • ¿Los nombres de archivos siguen una convención?
  • ¿Las pruebas unitarias están separadas de integración y end-to-end?
  • ¿Los archivos de prueba tienen un tamaño razonable?
  • ¿Las pruebas pueden ejecutarse en cualquier orden?
  • ¿Los helpers de prueba son simples y claros?
  • ¿La suite unitaria sigue siendo rápida?

19.20 Qué debes recordar de este tema

  • Una suite de pruebas es un conjunto de pruebas que se ejecutan juntas.
  • La organización debe facilitar encontrar, ejecutar y mantener pruebas.
  • Conviene usar nombres de archivos consistentes.
  • Las pruebas unitarias deben separarse de pruebas más lentas o con dependencias externas.
  • Las pruebas no deben depender del orden de ejecución.
  • Los archivos auxiliares deben reducir repetición sin ocultar complejidad.
  • Una suite unitaria debe mantenerse rápida y confiable.

19.21 Conclusión

Organizar bien archivos y suites de pruebas es una inversión en mantenibilidad. Una estructura clara ayuda a que las pruebas crezcan sin volverse caóticas.

La mejor organización es la que permite encontrar pruebas, entender su propósito, ejecutarlas con facilidad y mantener separadas las responsabilidades de cada tipo de prueba.

En el próximo tema veremos el ciclo de ejecución: ejecutar, fallar, corregir y repetir.