Pipelineschritte mit Assertions testen
Fügen Sie in jeder Phase Prüfungen der Zeilenanzahl, Nullwert-Assertions und Prüfungen erwarteter Spalten hinzu, damit Fehler sofort sichtbar werden.
Pipelineschritte mit Assertions testen ist eine kostenlose Pandas & NumPy Academy-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Pandas & NumPy Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Pandas & NumPy Academy-Kurs umfasst insgesamt 4 Lektionen.
Warum Pipelineschritte testen?
Eine Datenpipeline kann ohne Fehler durchlaufen und dennoch unbemerkt falsche Ausgaben erzeugen: etwa wenn Zeilen durch den falschen Filter entfernt werden, eine Spalte mit dem falschen Faktor multipliziert wird oder ein Merge Zeilen dupliziert, weil der Join-Schlüssel nicht eindeutig war. Die einzige Möglichkeit, solche unbemerkten Fehler zu erkennen, besteht darin, Assertions einzubauen, die erwartete Eigenschaften der Daten in jeder Pipelinestufe überprüfen. Assertions machen logische Fehler laut und sofort sichtbar.
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.Prüfungen der Zeilenanzahl
Prüfen Sie nach jedem Filterschritt per Assertion, ob die resultierende Zeilenanzahl innerhalb eines erwarteten Bereichs liegt. Zu wenige Zeilen bedeuten, dass der Filter zu aggressiv war; zu viele Zeilen weisen darauf hin, dass ein Join Datensätze dupliziert hat. Drücken Sie den erwarteten Bereich als Anteil der Eingabe aus: Bei fehlerfreien Daten sollte ein Schritt zum Entfernen von Nullwerten beispielsweise nie mehr als 30 % der Zeilen entfernen. Dieser Schutz erkennt unerwartete Änderungen der Datenqualität in vorgelagerten Quellen.
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 resultPrüfungen auf vorhandene Spalten
Prüfen Sie nach jeder Transformationsfunktion per Assertion, ob alle erwarteten Ausgabespalten vorhanden sind. Wenn ein Umbenennungsschritt versehentlich den falschen Schlüssel verwendet, fehlt die resultierende Spalte – der Fehler tritt jedoch möglicherweise erst viel später auf, wenn ein anderer Schritt sie verwenden möchte. Eine Assertion direkt nach der Transformation erkennt das Problem an seiner Quelle statt drei Schritte später mit einem verwirrenden KeyError.
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 dfAssertions für Wertebereiche
Prüfen Sie nach der Berechnung einer Umsatzspalte per Assertion, dass sie nicht negativ ist. Prüfen Sie nach dem Parsen von Datumsangaben, dass diese im erwarteten Jahresbereich liegen. Prüfen Sie nach der Kodierung von Kategorien, dass keine unerwarteten Codes vorkommen. Jede Assertion ist ein Datenvertrag, der das erwartete Verhalten dokumentiert und Verstöße frühzeitig erkennt. Schreiben Sie sie als Assertions und nicht als Print-Anweisungen, damit sie bei automatisierten Pipeline-Ausführungen Fehler auslösen.
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.')Schutz vor Duplikaten nach Merges
Ein häufiger Datenfehler ist ein Many-to-many-Merge, durch den sich die Zeilenanzahl versehentlich vervielfacht. Prüfen Sie nach jedem pd.merge() per Assertion, ob die Zeilenanzahl dem erwarteten Wert entspricht – bei einem Left-Join typischerweise also die Zeilenanzahl des linken DataFrames nicht überschreitet. Prüfen Sie außerdem per Assertion, ob die Schlüsselspalte eindeutig ist, sofern sie es sein sollte, damit Sie versehentliche Cross-Joins sofort erkennen.
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 resultNullwert-Assertion nach kritischen Schritten
Bestimmte Spalten dürfen zu keinem Zeitpunkt der Pipeline Nullwerte enthalten. Prüfen Sie mit df['key_col'].notna().all() nach jedem Schritt, der versehentlich Nullwerte einführen könnte – etwa nach einem Merge, bei dem einige Zeilen nicht zugeordnet werden (wodurch in den verbundenen Spalten NaN entsteht), oder nach einem map()-Aufruf, der für nicht zugeordnete Werte NaN zurückgibt. Machen Sie diese Assertions zu den letzten beiden Zeilen jeder Transformationsfunktion, die diese Spalten verarbeitet.
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 dfAufbau einer Testsuite für Pipelineschritte
Schreiben Sie für jede Pipelinefunktion Unit-Tests mit kleinen, von Hand erstellten DataFrames, die die zu testende Logik isolieren. Jeder Test sollte eine minimale Eingabe vorbereiten, die Funktion aufrufen und die Eigenschaften der Ausgabe per Assertion prüfen. Für einfache Pipelines reicht Pythons eingebautes assert aus; bei größeren Projekten verwenden Sie pytest, um vor der Bereitstellung alle Tests automatisch auszuführen.
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()Testen von Sonderfällen
Gute Tests decken nicht nur den Normalfall, sondern auch Sonderfälle ab: Eingaben mit ausschließlich Nullwerten, leere DataFrames, DataFrames mit einer einzigen Zeile und Spalten mit Extremwerten. Ein leerer DataFrame sollte einen leeren DataFrame zurückgeben und keinen Fehler auslösen. Ein DataFrame mit einer einzigen Zeile sollte das korrekte Ergebnis berechnen. Testen Sie diese Fälle ausdrücklich, damit die Pipeline sie in der Produktion problemlos verarbeitet, wenn ungewöhnliche Daten eintreffen.
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()Integrationstest: Die vollständige Pipeline mit Beispieldaten
Schreiben Sie zusätzlich zu Unit-Tests für einzelne Funktionen einen Integrationstest, der die vollständige Pipeline mit einer kleinen, repräsentativen Stichprobe realer Daten ausführt. Prüfen Sie per Assertion, dass die Ausgabe die erwartete Anzahl von Spalten enthält, die Schlüsselspalte eindeutig ist und der Gesamtumsatz in einem plausiblen Bereich liegt. Diese End-to-End-Prüfung erkennt Fehler im Zusammenspiel der einzelnen Schritte, die Unit-Tests nicht aufdecken.
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)Kontinuierliches Testen mit pytest
Wenn die Pipeline wächst, sammeln Sie alle Tests in einem Verzeichnis tests/ und führen Sie sie über die Kommandozeile mit pytest aus. Eine Datei conftest.py kann gemeinsam verwendete Fixtures wie Beispieldaten-Frames erstellen. Integrieren Sie pytest in Ihre CI/CD-Pipeline, damit bei jeder Codeänderung vor der Bereitstellung automatisch alle Tests ausgeführt werden. Ein fehlgeschlagener Test verhindert die Bereitstellung und damit, dass fehlerhafter Code die Produktion erreicht.
# 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')Assertions als lebende Dokumentation
Jede Assertion in der Pipeline ist zugleich Schutzmechanismus und Dokumentation: Sie beschreibt in maschinenlesbarer Form, wie die Daten an dieser Stelle aussehen müssen. Wenn eine neue Analystin oder ein neuer Analyst zum Projekt hinzukommt und den Pipeline-Code liest, vermitteln die Assertions die Datenverträge, ohne dass ein separates Spezifikationsdokument erforderlich ist. Behandeln Sie jede Assertion wie einen Kommentar – formulieren Sie die Meldung so aussagekräftig, dass die darin durchgesetzte Geschäftsregel verständlich ist.
# 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.')Kurze Überprüfung
Testen Sie Ihr Verständnis der Konzepte zur Datenanalyse aus dieser Lektion.
Zusammenfassung der Lektion
In dieser Lektion haben Sie gelernt: Prüfungen der Zeilenanzahl, des Vorhandenseins von Spalten, des Wertebereichs und von Nullwerten als Assertions direkt in die Pipeline einzubetten, Unit-Tests für einzelne Transformationsfunktionen mit Abdeckung von Sonderfällen zu schreiben sowie Integrationstests auszuführen und Assertions als lebende Dokumentation von Datenverträgen zu behandeln. Als Nächstes untersuchen wir die Planung und Protokollierung von Pipeline-Ausführungen für die tägliche automatische Ausführung.
Häufig gestellte Fragen
Ist die Lektion „Pipelineschritte mit Assertions testen“ kostenlos?
Ja — der vollständige Text von „Pipelineschritte mit Assertions testen“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Pandas & NumPy Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Pandas & NumPy Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Pipelineschritte mit Assertions testen“?
Fügen Sie in jeder Phase Prüfungen der Zeilenanzahl, Nullwert-Assertions und Prüfungen erwarteter Spalten hinzu, damit Fehler sofort sichtbar werden. Du übst Pandas & NumPy Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Pandas & NumPy Academy zu starten?
Keine Vorkenntnisse erforderlich. Pandas & NumPy Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.
Wie lange dauert die Lektion „Pipelineschritte mit Assertions testen“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Pandas & NumPy Academy-Lektion Code schreiben und ausführen?
Ja. Jede Pandas & NumPy Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Transformationsschritte als Funktionen strukturieren
- Pipelines mit Config-Dicts parametrisieren
- Pipelineschritte mit Assertions testen
- Pipeline-Läufe planen und protokollieren