Probar los pasos del pipeline con aserciones
Añada comprobaciones del número de filas, aserciones de valores nulos y validaciones de columnas esperadas en cada etapa para detectar los errores de inmediato.
Probar los pasos del pipeline con aserciones es una lección gratuita de Pandas & NumPy Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Pandas & NumPy Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Pandas & NumPy Academy incluye 4 lecciones en total.
¿Por qué probar los pasos del pipeline?
Un pipeline de datos que se ejecuta sin errores aún puede producir una salida incorrecta sin que nadie lo advierta: filas eliminadas por un filtro equivocado, una columna multiplicada por un factor incorrecto o una combinación que duplica filas porque la clave de unión no era única. La única forma de detectar estos fallos silenciosos es incorporar aserciones que verifiquen las propiedades esperadas de los datos en cada etapa del pipeline. Las aserciones convierten los errores lógicos en errores evidentes y visibles de inmediato.
import pandas as pd
import numpy as np
# A transform that looks correct but has a bug:
def compute_revenue_buggy(df):
# BUG: unit_price should be multiplied, not added
df['revenue'] = df['quantity'] + df['unit_price']
return df
# Without assertions, this runs silently with wrong numbers.Comprobaciones del número de filas
Después de cada paso de filtrado, compruebe mediante una aserción que el número de filas resultante se encuentre dentro del intervalo esperado. Muy pocas filas significa que el filtro fue demasiado restrictivo; demasiadas filas significa que una combinación duplicó registros. Exprese el intervalo esperado como una fracción de la entrada: por ejemplo, en datos en buen estado, un paso que elimine valores nulos nunca debería eliminar más del 30 % de las filas. Este control detecta cambios inesperados en la calidad de los datos de las fuentes ascendentes.
def drop_nulls_guarded(df, required_cols, max_drop_fraction=0.3):
before = len(df)
result = df.dropna(subset=required_cols)
after = len(result)
drop_fraction = (before - after) / before
assert drop_fraction <= max_drop_fraction, \
f'dropna removed {drop_fraction:.1%} of rows (limit {max_drop_fraction:.1%})'
return resultComprobaciones de existencia de columnas
Compruebe mediante una aserción que todas las columnas de salida esperadas existan después de cada función de transformación. Si un paso de renombrado utiliza accidentalmente la clave incorrecta, falta la columna resultante y el error solo aparece mucho después, cuando otro paso intenta utilizarla. Una aserción justo después de la transformación detecta el problema en su origen, en lugar de tres pasos más adelante mediante un KeyError confuso.
def compute_revenue(df):
df = df.assign(revenue=lambda d: d['quantity'] * d['unit_price'])
# Guard: check that the new column exists and is non-null
assert 'revenue' in df.columns, 'revenue column not created'
assert df['revenue'].notna().all(), 'revenue has unexpected NaNs'
return dfAserciones sobre rangos de valores
Después de calcular una columna de ingresos, compruebe mediante una aserción que sus valores no sean negativos. Después de analizar las fechas, compruebe que se encuentren dentro del intervalo de años esperado. Después de codificar las categorías, compruebe que no aparezcan códigos inesperados. Cada aserción es un contrato de datos que documenta el comportamiento esperado y detecta las infracciones de forma temprana. Escríbalas como aserciones en lugar de usar instrucciones de impresión, para que generen errores durante las ejecuciones automatizadas del pipeline.
def validate_computed_columns(df):
assert (df['revenue'] >= 0).all(), \
f'Negative revenue: {df[df["revenue"] < 0]["revenue"].head().tolist()}'
assert (df['quantity'] > 0).all(), \
'Non-positive quantity found'
assert df['revenue'].between(0, 1_000_000).all(), \
'Revenue out of plausible range'
print('Value range checks passed.')Controles para evitar duplicaciones después de las combinaciones
Un error común en los datos es una combinación de muchos a muchos que multiplica accidentalmente las filas. Después de cada pd.merge(), compruebe mediante una aserción que el número de filas sea el esperado; normalmente, que no supere el número de filas del DataFrame izquierdo en una combinación izquierda. Compruebe también que la columna clave sea única si debería serlo, para detectar de inmediato las combinaciones cruzadas accidentales.
def safe_merge(left, right, on, how='left'):
before = len(left)
result = left.merge(right, on=on, how=how)
after = len(result)
if how == 'left':
assert after == before, \
f'Left join increased rows from {before} to {after} — check key uniqueness in right df'
return resultAserción de valores nulos después de pasos críticos
Ciertas columnas nunca deben contener valores nulos en ningún punto del pipeline. Compruebe mediante una aserción df['key_col'].notna().all() después de cada paso que pudiera introducir valores nulos accidentalmente, como una combinación que no logra encontrar coincidencias para algunas filas (y produce NaN en las columnas combinadas) o una llamada a map() que devuelve NaN para valores sin correspondencia. Estas aserciones deben ser las dos últimas líneas de cada función de transformación que trabaje con esas columnas.
NOT_NULL_AFTER_TRANSFORM = ['order_id', 'revenue', 'category']
def post_transform_checks(df):
for col in NOT_NULL_AFTER_TRANSFORM:
null_count = df[col].isna().sum()
assert null_count == 0, \
f'{col}: {null_count} unexpected NaN values after transform'
print('Null checks passed.')
return dfCreación de una suite de pruebas para los pasos del pipeline
Escriba pruebas unitarias para cada función del pipeline utilizando DataFrames pequeños y creados manualmente que aíslen la lógica que se está probando. Cada prueba debe: preparar una entrada mínima, llamar a la función y comprobar mediante aserciones las propiedades de la salida. Usar el assert integrado de Python es suficiente para pipelines sencillos; en proyectos más grandes, utilice pytest para ejecutar automáticamente todas las pruebas antes del despliegue.
def test_compute_revenue():
test_df = pd.DataFrame({
'quantity': [2, 3],
'unit_price': [10.0, 5.0]
})
result = compute_revenue(test_df)
assert 'revenue' in result.columns
assert result['revenue'].tolist() == [20.0, 15.0]
assert result['revenue'].dtype == float
print('test_compute_revenue PASSED')
test_compute_revenue()Pruebas de casos límite
Las buenas pruebas no cubren únicamente el caso habitual, sino también casos límite: una entrada con todos sus valores nulos, un DataFrame vacío, un DataFrame de una sola fila y columnas con valores extremos. Un DataFrame vacío debe devolver otro DataFrame vacío, no generar un error. Un DataFrame con una sola fila debe calcular el resultado correcto. Pruebe explícitamente estos casos para garantizar que el pipeline los gestione correctamente en producción cuando lleguen datos inusuales.
def test_empty_df():
empty = pd.DataFrame({'quantity': [], 'unit_price': []})
result = compute_revenue(empty)
assert len(result) == 0, 'Empty input should produce empty output'
assert 'revenue' in result.columns, 'Revenue column should still be created'
print('test_empty_df PASSED')
def test_single_row():
single = pd.DataFrame({'quantity': [1], 'unit_price': [99.0]})
result = compute_revenue(single)
assert result['revenue'].iloc[0] == 99.0
print('test_single_row PASSED')
test_empty_df()
test_single_row()Prueba de integración: pipeline completo con datos de ejemplo
Además de las pruebas unitarias de funciones individuales, escriba una prueba de integración que ejecute el pipeline completo con una muestra pequeña y representativa de datos reales. Compruebe mediante aserciones que la salida tenga el número esperado de columnas, que la columna clave sea única y que los ingresos totales se encuentren dentro de un intervalo plausible. Esta comprobación de extremo a extremo detecta errores en la interacción entre pasos que las pruebas unitarias no revelan.
def integration_test(config):
raw = extract(config)
clean = transform(raw, config)
assert set(config['required_cols']).issubset(set(clean.columns))
assert clean['order_id'].is_unique
assert (clean['revenue'] >= 0).all()
assert len(clean) > 0
print(f'Integration test PASSED. Output: {clean.shape}')
integration_test(CONFIG)Pruebas continuas con pytest
A medida que crezca el pipeline, reúna todas las pruebas en un directorio tests/ y ejecútelas con pytest desde la línea de comandos. Un archivo conftest.py puede crear fixtures compartidos, como DataFrames de ejemplo. Integre pytest en su pipeline de CI/CD para que cada cambio de código ejecute automáticamente todas las pruebas antes del despliegue. Una prueba fallida bloquea el despliegue y evita que el código defectuoso llegue a producción.
# tests/test_transform.py — example structure
# import pytest, pandas as pd
# from pipeline.transform import compute_revenue, drop_nulls
# @pytest.fixture
# def sample_df():
# return pd.DataFrame({'quantity': [2, 3], 'unit_price': [10.0, 5.0]})
# def test_revenue(sample_df):
# result = compute_revenue(sample_df)
# assert result['revenue'].tolist() == [20.0, 15.0]
print('Run: pytest tests/ -v to execute all pipeline tests')Las aserciones como documentación viva
Cada aserción del pipeline es tanto un control como un elemento de documentación: expresa, en una forma que la máquina puede interpretar, cómo deben ser los datos en ese punto. Cuando un analista nuevo se incorpora al proyecto y lee el código del pipeline, las aserciones le muestran los contratos de datos sin necesidad de consultar un documento de especificaciones independiente. Trate cada aserción como trataría un comentario: haga que el mensaje sea lo bastante descriptivo para comprender la regla de negocio que aplica.
# These assertions document business rules as code:
assert (df['order_date'] >= pd.Timestamp('2020-01-01')).all(), \
'Company was founded 2020-01-01; no orders can predate this'
assert df['region'].isin({'North', 'South', 'East', 'West', 'Central'}).all(), \
'Only 5 sales regions are valid; new regions require config update'
print('Business rules verified as assertions.')Comprobación rápida
Compruebe su comprensión de los conceptos de análisis de datos de esta lección.
Resumen de la lección
En esta lección ha aprendido a: incorporar comprobaciones del número de filas, la existencia de columnas, el rango de valores y los valores nulos como aserciones dentro del pipeline, escribir pruebas unitarias para funciones de transformación individuales con cobertura de casos límite y ejecutar pruebas de integración y tratar las aserciones como documentación viva de los contratos de datos. A continuación, exploraremos cómo programar y registrar las ejecuciones del pipeline para automatizar su ejecución diaria.
Preguntas frecuentes
¿La lección «Probar los pasos del pipeline con aserciones» es gratis?
Sí — el texto completo de «Probar los pasos del pipeline con aserciones» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Pandas & NumPy Academy, actualiza a CoddyKit PRO. El curso de Pandas & NumPy Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Probar los pasos del pipeline con aserciones»?
Añada comprobaciones del número de filas, aserciones de valores nulos y validaciones de columnas esperadas en cada etapa para detectar los errores de inmediato. Practicas Pandas & NumPy Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Pandas & NumPy Academy?
No se requiere experiencia previa. Pandas & NumPy Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.
¿Cuánto tiempo toma la lección «Probar los pasos del pipeline con aserciones»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Pandas & NumPy Academy?
Sí. Cada lección de Pandas & NumPy Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Estructurar los pasos de transformación como funciones
- Parametrizar pipelines con diccionarios de configuración
- Probar los pasos del pipeline con aserciones
- Programar y registrar ejecuciones del pipeline