Data Engineering
Stop unit-testing your pipelines. Property-test them.
Every data team I’ve joined had the same ritual: hundreds of unit tests mocking a dataframe, asserting transformation logic that almost never changes. And every few months, production still broke - not because the logic was wrong, but because the data didn’t look like the mock.
Unit tests assert that your code is correct. Pipelines fail because your assumptions about the data are wrong. Those are different failure modes, and they need a different tool.
Assert properties, not examples
A property is a statement that must hold for any valid input: the row count is preserved by a dedupe unless duplicates existed, a sum is invariant under partitioning, no nulls sneak into a not-null column. Property-based testing generates hundreds of ugly inputs and hunts for the one that violates your invariant.
@given(st.lists(st.integers()))
def test_dedupe_preserves_distinct(xs):
assert dedupe(xs) == list(set(xs))Your code is rarely wrong. Your assumptions about your data almost always are.
We replaced a 400-case mocked unit suite with 60 property tests and a handful of dataset-level expectations. Coverage went down on paper. Incidents from silent schema drift went to zero. The next post covers how we wired those expectations into dbt so they run on every merge.