Catching the moment your data lies to you.
Data Engineering Module 1Check the code that processes data — gates the CI build.
Check the data the code processed — gates the pipeline run.
Different lifecycles, different alerting. A unit test passing does not mean today's data is good.
| Term | What it is |
|---|---|
| Expectation | A single assertion about data (e.g., "column X is never null"). |
| Suite | A named bundle of expectations applied to one table. |
| Checkpoint | A scheduled run of a suite against fresh data. |
| Data docs | Generated HTML reports of run results. |
import great_expectations as gx
context = gx.get_context()
dx = context.sources.add_pandas("gh").read_parquet("data/parquet/date=2024-01-01/")
result = dx.expect_column_values_to_not_be_null("type")
print(result.success) # True
One call. One assertion. Returns a result object with success, observed value, and a sample of unexpected rows.
Expectations to add to the gharchive events table:
expect_column_to_exist for type, actor, repo, created_atexpect_column_values_to_not_be_null for all fourexpect_column_values_to_be_in_set for type (the known event types)expect_column_values_to_match_strftime_format for created_at (%Y-%m-%dT%H:%M:%SZ)expect_table_row_count_to_be_between (sanity bounds)expect_column_values_to_be_in_setThe set of GitHub event types changes slowly but does change (e.g., DiscussionEvent added in 2020). Pin the known set; let the expectation fail loudly when a new value appears; then decide whether to accept or reject the new type.
This is not a bug to fix in code — it is a data contract decision. Document it. Update the expectation. Tell downstream consumers.
| Severity | Example | Action |
|---|---|---|
| block-the-pipeline | required column missing | fail loudly; alert on-call; do not load downstream. |
| warn-but-load | new event type appeared | annotate the load; surface in dashboards; review in standup. |
| info | row count up 10% week-over-week | dashboard only; no alert. |
extract -> transform -> [VALIDATE] -> load -> downstream
The validate step is between transform and load — sometimes also right after extract. On failure, the load step is skipped.
sample-pipeline/
extract/
transform/
quality/
expectations.py # the suite
checkpoints/ # GE-generated
data_docs/ # GE-generated HTML
Full schema contracts (Lesson 13), automated profiling (Lesson 12), CI integration of suites (Lesson 06). Today: a hand-written suite, running locally, against the L02 output.
One step at a time. The primitives you learn here are the building blocks for all of those advanced patterns.