0Pricing
Pandas & NumPy Academy · Aula

Testando etapas do pipeline com asserções

Adicione verificações da contagem de linhas, asserções de valores nulos e verificações das colunas esperadas em cada etapa para que os erros apareçam imediatamente.

Testando etapas do pipeline com asserções é uma aula grátis de Pandas & NumPy Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Pandas & NumPy Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Pandas & NumPy Academy inclui 4 aulas no total.

Por que testar as etapas do fluxo de dados?

Um fluxo de dados que é executado sem erros ainda pode produzir uma saída incorreta sem emitir avisos: linhas removidas pelo filtro errado, uma coluna multiplicada pelo fator incorreto ou uma mesclagem que duplica linhas porque a chave de junção não era exclusiva. A única forma de detectar essas falhas silenciosas é incorporar asserções que verifiquem as propriedades esperadas dos dados em cada etapa do fluxo de dados. As asserções transformam erros lógicos em erros evidentes e imediatamente visíveis.

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.

Verificações da quantidade de linhas

Após cada etapa de filtragem, verifique por asserção se a quantidade resultante de linhas está dentro do intervalo esperado. Poucas linhas demais indicam que o filtro foi agressivo em excesso; linhas demais indicam que uma junção duplicou registros. Expresse o intervalo esperado como uma fração da entrada: por exemplo, em dados íntegros, uma etapa de remoção de valores nulos nunca deve remover mais de 30% das linhas. Essa proteção detecta alterações inesperadas na qualidade dos dados das fontes upstream.

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 result

Verificações da existência de colunas

Verifique por asserção se todas as colunas de saída esperadas existem após cada função de transformação. Se uma etapa de renomeação usar acidentalmente a chave errada, a coluna resultante ficará ausente — e o erro só aparecerá muito mais tarde, quando outra etapa tentar usá-la. Uma asserção logo após a transformação identifica o problema na origem, em vez de três etapas depois, com um 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 df

Asserções de intervalo de valores

Depois de calcular uma coluna de receita, verifique por asserção se ela não contém valores negativos. Depois de analisar datas, verifique por asserção se elas estão dentro do intervalo de anos esperado. Depois de codificar categorias, verifique por asserção se não aparecem códigos inesperados. Cada asserção é um contrato de dados que documenta o comportamento esperado e detecta violações antecipadamente. Escreva-as como asserções, e não como instruções de impressão, para que gerem erros em execuções automatizadas do fluxo de dados.

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.')

Proteções contra duplicação após mesclagens

Um erro comum em dados é uma mesclagem muitos-para-muitos que multiplica linhas acidentalmente. Após cada pd.merge(), verifique por asserção se a quantidade de linhas é a esperada — normalmente, se não excedeu a quantidade de linhas do DataFrame esquerdo em uma junção à esquerda. Verifique também se a coluna-chave é exclusiva quando deveria ser, para detectar imediatamente junções cruzadas acidentais.

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 result

Asserção de valores nulos após etapas críticas

Determinadas colunas nunca devem conter valores nulos em nenhum ponto do fluxo de dados. Verifique df['key_col'].notna().all() após cada etapa que possa introduzir valores nulos acidentalmente — como uma mesclagem que não consegue corresponder a algumas linhas (produzindo NaN nas colunas mescladas) ou uma chamada a map() que retorna NaN para valores não mapeados. Faça dessas as duas últimas linhas de toda função de transformação que manipule essas colunas.

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 df

Criando um conjunto de testes para as etapas do fluxo de dados

Escreva testes unitários para cada função do fluxo de dados usando pequenos DataFrames criados manualmente, que isolem a lógica sendo testada. Cada teste deve: preparar uma entrada mínima, chamar a função e verificar por asserção as propriedades da saída. Usar o assert integrado ao Python é suficiente para fluxos de dados simples; em projetos maiores, use pytest para executar todos os testes automaticamente antes da implantação.

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()

Testando casos extremos

Bons testes abrangem não apenas o caminho esperado, mas também casos extremos: entrada totalmente nula, DataFrame vazio, DataFrame com uma única linha e colunas com valores extremos. Um DataFrame vazio deve retornar um DataFrame vazio, não um erro. Um DataFrame com uma única linha deve calcular o resultado correto. Teste esses casos explicitamente para garantir que o fluxo de dados os trate adequadamente em produção quando chegarem dados incomuns.

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()

Teste de integração: fluxo de dados completo com dados de exemplo

Além dos testes unitários de funções individuais, escreva um teste de integração que execute o fluxo de dados completo em uma pequena amostra representativa de dados reais. Verifique por asserção se a saída tem a quantidade esperada de colunas, se a coluna-chave é exclusiva e se a receita total está dentro de um intervalo plausível. Essa verificação de ponta a ponta detecta erros na interação entre as etapas que os testes unitários não revelam.

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)

Testes contínuos com pytest

À medida que o fluxo de dados cresce, reúna todos os testes em um diretório tests/ e execute-os com pytest pela linha de comando. Um arquivo conftest.py pode criar elementos de teste compartilhados, como DataFrames de exemplo. Integre o pytest ao seu fluxo de dados de CI/CD para que toda alteração no código execute automaticamente todos os testes antes da implantação. Um teste com falha bloqueia a implantação e impede que código defeituoso chegue à produção.

# 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')

Asserções como documentação viva

Cada asserção no fluxo de dados é tanto uma proteção quanto uma forma de documentação: ela declara, em formato legível por máquina, como os dados devem estar naquele ponto. Quando um novo analista entra no projeto e lê o código do fluxo de dados, as asserções informam os contratos de dados sem exigir um documento de especificação separado. Trate cada asserção como trataria um comentário — torne a mensagem descritiva o suficiente para permitir a compreensão da regra de negócio que ela impõe.

# 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.')

Verificação rápida

Teste sua compreensão dos conceitos de Análise de Dados desta lição.

Recapitulação da lição

Nesta lição, você aprendeu a: incorporar verificações da quantidade de linhas, da existência de colunas, do intervalo de valores e de valores nulos como asserções no fluxo de dados, escrever testes unitários para funções de transformação individuais, abrangendo casos extremos e executar testes de integração e tratar asserções como documentação viva dos contratos de dados. A seguir, exploraremos o agendamento e o registro das execuções do fluxo de dados para permitir a execução diária automatizada.

Perguntas Frequentes

A aula “Testando etapas do pipeline com asserções” é grátis?

Sim — o texto completo de “Testando etapas do pipeline com asserções” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Pandas & NumPy Academy, atualize para CoddyKit PRO. O curso de Pandas & NumPy Academy inclui 4 aulas no total.

O que vou aprender em “Testando etapas do pipeline com asserções”?

Adicione verificações da contagem de linhas, asserções de valores nulos e verificações das colunas esperadas em cada etapa para que os erros apareçam imediatamente. Você pratica Pandas & NumPy Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Pandas & NumPy Academy?

Nenhuma experiência prévia é necessária. Pandas & NumPy Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.

Quanto tempo leva a aula “Testando etapas do pipeline com asserções”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Pandas & NumPy Academy?

Sim. Cada aula de Pandas & NumPy Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Estruturando etapas de transformação como funções
  2. Parametrizando pipelines com dicionários de configuração
  3. Testando etapas do pipeline com asserções
  4. Agendando e registrando execuções do pipeline
← Voltar para Pandas & NumPy Academy