Skip to main content

Great Expectations: Data Quality Validation & Testing Guide

Great Expectations is the leading open-source Python library for data quality validation. Define a contract for your data, validate every pipeline run against it, generate human-readable documentation, and catch bad data before it reaches production systems.

✓ 300+ built-in expectations ✓ Auto-generated Data Docs ✓ Airflow / Prefect integration ✓ Spark & SQL support

What is Great Expectations?

Great Expectations (GE) is an open-source Python library for defining, documenting, and enforcing data quality expectations in data pipelines. Instead of writing ad-hoc assertions scattered across pipeline code, GE provides a structured framework: define Expectation Suites (quality contracts), connect them to data via Validators, and run them at checkpoints in your pipeline. Failed validations can block pipeline execution or trigger alerts before bad data propagates downstream.

GE works with Pandas DataFrames, Spark DataFrames, SQL databases (via SQLAlchemy), and files (CSV, Parquet, JSON). The Data Docs feature auto-generates an HTML documentation site showing all expectations, their validation history, and observed values — making data quality transparent to all stakeholders without requiring access to the pipeline code.

Creating an Expectation Suite

# pip install great-expectations
import great_expectations as gx

# Initialize a Data Context (creates gx/ config directory)
context = gx.get_context()

# Connect to a Pandas datasource
datasource = context.sources.add_pandas("my_datasource")
asset = datasource.add_csv_asset("orders", filepath_or_buffer="orders.csv")
batch_request = asset.build_batch_request()

# Create an Expectation Suite
suite = context.add_expectation_suite("orders_suite")

# Get a Validator (loads a batch + attaches the suite)
validator = context.get_validator(
    batch_request=batch_request,
    expectation_suite_name="orders_suite",
)

# Define expectations
validator.expect_column_to_exist("order_id")
validator.expect_column_values_to_not_be_null("order_id")
validator.expect_column_values_to_be_unique("order_id")
validator.expect_column_values_to_not_be_null("amount")
validator.expect_column_values_to_be_between("amount", min_value=0, max_value=1_000_000)
validator.expect_column_values_to_be_in_set(
    "status", ["placed", "shipped", "delivered", "returned"]
)
validator.expect_column_values_to_match_regex(
    "email", r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$"
)
validator.expect_table_row_count_to_be_between(min_value=1000, max_value=10_000_000)

# Save expectations to the suite
validator.save_expectation_suite(discard_failed_expectations=False)
print("Suite saved with", len(suite.expectations), "expectations")

Checkpoints, Data Docs & Alerts

# Checkpoint — run validations and build Data Docs
import great_expectations as gx

context = gx.get_context()

# Add a checkpoint that links a suite to a datasource
checkpoint = context.add_checkpoint(
    name="orders_checkpoint",
    validations=[
        {
            "batch_request": {
                "datasource_name": "my_datasource",
                "data_asset_name": "orders",
            },
            "expectation_suite_name": "orders_suite",
        }
    ],
    action_list=[
        {
            "name": "store_validation_result",
            "action": {"class_name": "StoreValidationResultAction"},
        },
        {
            "name": "update_data_docs",
            "action": {"class_name": "UpdateDataDocsAction"},
        },
        {
            "name": "send_slack_notification",
            "action": {
                "class_name": "SlackNotificationAction",
                "slack_webhook": "https://hooks.slack.com/...",
                "notify_on": "failure",
            },
        },
    ],
)

# Run the checkpoint
result = context.run_checkpoint(checkpoint_name="orders_checkpoint")

if not result["success"]:
    raise ValueError("Data validation FAILED — blocking pipeline execution!")

# Open Data Docs in browser
context.open_data_docs()

Integrating GE into an Airflow Pipeline

# Integrate Great Expectations into an Airflow DAG
from airflow import DAG
from airflow.operators.python import PythonOperator
from datetime import datetime
import great_expectations as gx

def validate_data(**context):
    gx_context = gx.get_context(
        context_root_dir="/opt/airflow/gx"
    )
    result = gx_context.run_checkpoint(
        checkpoint_name="orders_checkpoint",
        batch_parameters={
            "partition_date": context["ds"]  # pass Airflow execution date
        },
    )
    if not result["success"]:
        failed = [
            r["expectation_config"]["expectation_type"]
            for r in result["run_results"].values()
            for r in r["validation_result"]["results"]
            if not r["success"]
        ]
        raise ValueError(f"Validation failed for: {failed}")

with DAG("etl_with_validation", schedule_interval="@daily",
         start_date=datetime(2024, 1, 1), catchup=False) as dag:
    validate = PythonOperator(
        task_id="validate_orders",
        python_callable=validate_data,
    )
    transform = PythonOperator(task_id="transform", python_callable=run_transform)
    validate >> transform  # block transform if validation fails

Great Expectations vs dbt Tests vs Soda

Feature Great Expectations dbt Tests Soda
Configuration Python API YAML in schema.yml YAML (.soda)
Works on Files, Pandas, Spark, SQL dbt models (SQL only) SQL + Spark + Pandas
Documentation Auto Data Docs (HTML) dbt docs (lineage) Soda Cloud UI
Alerting Slack/email via Actions Orchestrator-level Built-in (Soda Cloud)
Raw data validation Yes (at ingestion) No (post-transform) Yes
Setup complexity High Low (within dbt) Medium

Frequently Asked Questions

What is an Expectation Suite in Great Expectations?▼

An Expectation Suite is a named, versioned collection of expectations for a dataset — essentially a schema and quality contract. Each expectation is a declarative assertion like 'column X must not be null' or 'column Y values must be between 0 and 100'. Suites are stored as JSON files in the GE store and can be version-controlled. You create a suite once using a Validator, and then re-run it against new batches of data at any time. Suites can be auto-generated from a profiler that analyzes existing data, then manually refined.

What is a Checkpoint and when should I use it?▼

A Checkpoint is the mechanism for running validations in a production context. It links one or more Expectation Suites to one or more data batches and defines a list of actions to perform after validation — storing results, updating Data Docs, sending Slack/email alerts, or raising exceptions. Checkpoints are the integration point between Great Expectations and your pipeline orchestrator (Airflow, Prefect, dbt). Call context.run_checkpoint() in your pipeline and check result['success'] to decide whether to allow the pipeline to proceed.

What are Data Docs in Great Expectations?▼

Data Docs are auto-generated HTML documentation sites that display your Expectation Suites, validation results, and profiling reports. They show which expectations passed and failed, with actual observed values alongside expected values. Data Docs can be hosted locally, on S3, GCS, or Azure Blob Storage. They serve as living documentation of your data quality contract — stakeholders and data consumers can see exactly what guarantees are in place and review historical validation runs. Update them automatically via the UpdateDataDocsAction in your Checkpoint action list.

How does Great Expectations differ from dbt tests?▼

dbt tests run inside the warehouse against materialized models — they are SQL-based and tightly coupled to dbt's transformation layer. They are best for testing transformed data after dbt run. Great Expectations runs in Python before or after loading, works on raw data, DataFrames, and files (not just warehouse tables), and provides richer statistical expectations (distribution checks, outlier detection, format validation). They are complementary: use dbt tests for model output validation and Great Expectations for input data validation at the ingestion boundary.

Can Great Expectations work with Spark DataFrames?▼

Yes. Great Expectations has native Spark support through the SparkDFDataset and the Spark Datasource in GE version 3+. You can validate PySpark DataFrames directly without materializing them to disk. This is useful for validating streaming or batch Spark pipelines at transformation boundaries. The Spark backend evaluates expectations as Spark SQL operations distributed across the cluster, making it efficient for large datasets. Configure a SparkDFDatasource in your Data Context and pass a Spark DataFrame as the batch.

What is the difference between Great Expectations, Soda, and dbt tests?▼

Great Expectations is the most feature-rich and flexible — a full Python library with hundreds of expectation types, Data Docs, custom expectations, and deep integration with data sources. It has a steeper setup curve. Soda is a more developer-friendly, YAML-driven tool with a managed cloud offering (Soda Cloud) for teams that want built-in alerting and a SaaS UI without hosting infrastructure. dbt tests are the simplest option but only work within dbt's transformation layer and are limited to generic and singular SQL tests. For teams deeply invested in dbt, start with dbt tests. For standalone ingestion validation, choose GE or Soda.

Share this tool: X / Twitter LinkedIn
✓ 60,000+ developers use DevPlaybook ★★★★★ 4.8 / 5 on Gumroad ✓ MIT licensed · Instant download ✓ No login required

Related Products

on Gumroad

You Might Also Need

More Free Tools

Enjoying this tool? Get more like it.

Weekly developer tool guides, productivity playbooks & AI tricks. Free. No spam.

DevPlaybook Pro 7 days free

Unlock AI-Powered Dev Tools

  • ⚡ AI Code Review, Doc Generator & SQL Builder
  • ⚡ All premium templates & early access
  • ⚡ Member discounts on Gumroad products
Start Free Trial →

$9/mo after trial · Cancel anytime

Want the full toolkit?

Get DevPlaybook Pro

Every template, guide, boilerplate, and automation script in one bundle. 13 premium products — grab them all at once and save big.

$79
$241 separately Save $162 (67% off)
Get DevPlaybook Pro — $79 →

MIT licensed · Instant download · No subscription

See what's included → Browse all deals →