Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Give agents more agency

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    sfc-gh-dflippo

    dbt-testing

    sfc-gh-dflippo/dbt-testing
    Data & Analytics
    26

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    dbt testing strategies using dbt_constraints for database-level enforcement, generic tests, and singular tests...

    SKILL.md

    dbt Testing

    Purpose

    Transform AI agents into experts on dbt testing strategies, providing guidance on implementing comprehensive data quality checks with database-enforced constraints, generic tests, and custom singular tests to ensure data integrity across all layers.

    When to Use This Skill

    Activate this skill when users ask about:

    • Implementing data quality tests
    • Adding primary key and foreign key constraints
    • Using dbt_constraints package for database-level enforcement
    • Creating generic (reusable) tests
    • Writing singular (one-off) tests
    • Testing strategies by layer (bronze/silver/gold)
    • Debugging test failures
    • Configuring test severity levels
    • Storing test failures for analysis

    Official dbt Documentation: Testing


    Testing Philosophy

    Implement tests in this order for maximum data quality:

    1. Primary Keys - Every dimension must have one
    2. Foreign Keys - All fact relationships
    3. Unique Keys - Business key constraints
    4. Business Rules - Domain-specific validations
    5. Data Quality - Completeness, accuracy, consistency

    Why Use dbt_constraints?

    The dbt_constraints package provides database-level enforcement (not just dbt tests):

    ✅ Database Enforcement - Creates actual constraints in the data warehouse ✅ Performance - Database-level constraints improve query optimization ✅ Data Integrity - Prevents invalid data at all access points (not just dbt) ✅ Documentation - Constraints visible in database metadata and BI tools ✅ Query Optimization - Database can use constraints for better execution plans

    Standard dbt tests only validate during dbt test runs. dbt_constraints creates real database constraints that are enforced 24/7.

    Official dbt_constraints Documentation: GitHub - Snowflake-Labs/dbt_constraints


    Package Installation

    # packages.yml
    packages:
      - package: Snowflake-Labs/dbt_constraints
        version: [">=0.8.0", "<1.0.0"]
    
      - package: dbt-labs/dbt_utils
        version: [">=1.0.0", "<2.0.0"]
    

    Install packages:

    dbt deps
    

    Official dbt Docs: Package Management


    Primary Key Testing

    Simple Primary Key (dbt_constraints)

    Required for every dimension:

    # models/gold/_models.yml
    models:
      - name: dim_customers
        columns:
          - name: customer_id
            tests:
              - dbt_constraints.primary_key
    

    Composite Primary Key

    When primary key spans multiple columns:

    models:
      - name: fct_order_lines
        tests:
          - dbt_constraints.primary_key:
              column_names:
                - order_id
                - line_number
    

    Alternative: Built-in dbt Tests

    Not recommended - no database enforcement:

    columns:
      - name: product_id
        tests:
          - not_null
          - unique
    

    Limitation: Only validates during dbt test runs, doesn't prevent bad data from other sources.


    Foreign Key Testing

    Simple Foreign Key (dbt_constraints)

    Ensures referential integrity:

    models:
      - name: fct_orders
        columns:
          - name: customer_id
            tests:
              - dbt_constraints.foreign_key:
                  pk_table_name: ref('dim_customers')
                  pk_column_name: customer_id
    

    Multiple Foreign Keys

    For facts with multiple dimension relationships:

    models:
      - name: fct_order_lines
        columns:
          - name: order_id
            tests:
              - dbt_constraints.foreign_key:
                  pk_table_name: ref('fct_orders')
                  pk_column_name: order_id
    
          - name: product_id
            tests:
              - dbt_constraints.foreign_key:
                  pk_table_name: ref('dim_products')
                  pk_column_name: product_id
    
          - name: customer_id
            tests:
              - dbt_constraints.foreign_key:
                  pk_table_name: ref('dim_customers')
                  pk_column_name: customer_id
    

    Alternative: Built-in dbt Relationships Test

    Not recommended - no database enforcement:

    columns:
      - name: customer_id
        tests:
          - relationships:
              to: ref('dim_customers')
              field: customer_id
    

    Unique Key Testing

    Simple Unique Key (dbt_constraints)

    For business keys (non-primary keys that must be unique):

    columns:
      - name: customer_email
        tests:
          - dbt_constraints.unique_key
    

    Composite Unique Key

    When uniqueness spans multiple columns:

    models:
      - name: stg_orders
        tests:
          - dbt_constraints.unique_key:
              column_names:
                - order_number
                - order_source
    

    Generic Tests (Reusable)

    Built-in dbt Tests

    columns:
      - name: order_status
        tests:
          - not_null
          - accepted_values:
              values: ["pending", "processing", "shipped", "delivered", "cancelled"]
    
      - name: order_amount
        tests:
          - not_null
    

    dbt_utils Tests

    Powerful generic tests from dbt_utils package:

    columns:
      - name: customer_email
        tests:
          - dbt_utils.not_null_proportion:
              at_least: 0.95 # 95% of rows must have email
    
      - name: order_amount
        tests:
          - dbt_utils.accepted_range:
              min_value: 0
              max_value: 1000000
    
      - name: customer_status
        tests:
          - dbt_utils.not_empty_string
    

    Official dbt_utils Documentation: dbt_utils - Generic Tests


    Custom Generic Tests

    Create reusable test for common patterns:

    -- tests/generic/test_positive_values.sql
    {% test positive_values(model, column_name) %}
    
    select count(*)
    from {{ model }}
    where {{ column_name }} <= 0
    
    {% endtest %}
    

    Usage:

    columns:
      - name: order_total
        tests:
          - positive_values
    
      - name: quantity
        tests:
          - positive_values
    

    Another Example: Date Range Test

    -- tests/generic/test_recent_data.sql
    {% test recent_data(model, column_name, days_ago=30) %}
    
    select count(*)
    from {{ model }}
    where {{ column_name }} < dateadd(day, -{{ days_ago }}, current_date())
    
    {% endtest %}
    

    Usage:

    columns:
      - name: order_date
        tests:
          - recent_data:
              days_ago: 7 # Alert if no orders in last 7 days
    

    Singular Tests (One-Off)

    For complex business logic that doesn't fit generic tests:

    -- tests/singular/test_order_dates_sequential.sql
    with date_validation as (
        select
            o.order_id,
            o.order_date,
            c.signup_date
        from {{ ref('fct_orders') }} o
        join {{ ref('dim_customers') }} c
            on o.customer_id = c.customer_id
        where o.order_date < c.signup_date  -- Order before signup = invalid
    )
    
    select * from date_validation
    

    Test fails if ANY rows are returned.

    More Singular Test Examples

    Revenue Reconciliation:

    -- tests/singular/test_revenue_reconciliation.sql
    -- Ensure fact table revenue matches source system
    with fact_revenue as (
        select sum(order_amount) as total_revenue
        from {{ ref('fct_orders') }}
        where order_date = current_date() - 1
    ),
    
    source_revenue as (
        select sum(amount) as total_revenue
        from {{ source('erp', 'orders') }}
        where order_date = current_date() - 1
    ),
    
    comparison as (
        select
            f.total_revenue as fact_revenue,
            s.total_revenue as source_revenue,
            abs(f.total_revenue - s.total_revenue) as difference
        from fact_revenue f
        cross join source_revenue s
    )
    
    select * from comparison
    where difference > 0.01  -- Tolerance of 1 cent
    

    Referential Integrity Check:

    -- tests/singular/test_orphaned_orders.sql
    -- Find orders with invalid customer_id (not in dim_customers)
    select
        o.order_id,
        o.customer_id
    from {{ ref('fct_orders') }} o
    left join {{ ref('dim_customers') }} c
        on o.customer_id = c.customer_id
    where c.customer_id is null
      and o.customer_id != -1  -- Exclude ghost key
    

    Official dbt Documentation: Singular Tests


    Testing by Layer

    Bronze Layer (Staging)

    Focus: Basic data quality at source

    models:
      - name: stg_tpc_h__customers
        columns:
          - name: customer_id
            tests:
              - dbt_constraints.primary_key
    
          - name: customer_email
            tests:
              - not_null
    

    Keep it simple - just verify source data integrity.


    Silver Layer (Intermediate)

    Focus: Business rule validation, calculated fields

    models:
      - name: int_customers__with_orders
        columns:
          - name: customer_id
            tests:
              - dbt_constraints.primary_key
    
          - name: lifetime_orders
            tests:
              - not_null
              - dbt_utils.accepted_range:
                  min_value: 0
    
          - name: lifetime_value
            tests:
              - not_null
              - dbt_utils.accepted_range:
                  min_value: 0
    

    Add business logic validation - ensure calculated fields make sense.


    Gold Layer (Marts)

    Focus: Comprehensive constraint enforcement with dbt_constraints

    models:
      - name: dim_customers
        description: "Customer dimension with full history and metrics"
        columns:
          - name: customer_id
            description: "Unique customer identifier"
            tests:
              - dbt_constraints.primary_key
    
          - name: customer_tier
            description: "Customer value classification"
            tests:
              - accepted_values:
                  values: ["bronze", "silver", "gold", "platinum"]
    
          - name: customer_email
            tests:
              - dbt_constraints.unique_key
    
      - name: fct_orders
        description: "Order transactions fact table"
        columns:
          - name: order_id
            tests:
              - dbt_constraints.primary_key
    
          - name: customer_id
            tests:
              - dbt_constraints.foreign_key:
                  pk_table_name: ref('dim_customers')
                  pk_column_name: customer_id
    
          - name: product_id
            tests:
              - dbt_constraints.foreign_key:
                  pk_table_name: ref('dim_products')
                  pk_column_name: product_id
    
          - name: order_amount
            tests:
              - not_null
              - dbt_utils.accepted_range:
                  min_value: 0
    

    Maximum enforcement - use all constraint types to ensure production data quality.


    Test Configuration

    Store Test Failures

    Analyze failed test records:

    dbt test --store-failures
    
    # dbt_project.yml
    tests:
      +store_failures: true
      +schema: dbt_test_failures
    

    Query failures:

    select * from dbt_test_failures.not_null_dim_customers_customer_email
    

    Test Severity Levels

    Warn vs Error:

    columns:
      - name: customer_email
        tests:
          - dbt_constraints.unique_key:
              config:
                severity: warn # or 'error' (default)
    

    Severity Behavior:

    • error: Test failure stops dbt execution (exit code 1)
    • warn: Test failure logs warning but continues (exit code 0)

    Use warn for:

    • Data quality checks that shouldn't block deployment
    • Known edge cases during migration
    • Monitoring tests

    Limit Test Execution

    Test specific model:

    dbt test --select dim_customers
    

    Test by type:

    dbt test --select test_type:generic    # All generic tests
    dbt test --select test_type:singular   # All singular tests
    

    Test with dependencies:

    dbt test --select +dim_customers+  # Test model and all dependencies
    

    Official dbt Documentation: Test Selection


    Running Tests

    # Run all tests
    dbt test
    
    # Build models and test together (recommended)
    dbt build  # Runs models, then tests
    
    # Test specific model
    dbt test --select dim_customers
    
    # Test specific column
    dbt test --select dim_customers,column:customer_id
    
    # Test by layer
    dbt test --select tag:gold
    
    # Test with failures stored
    dbt test --store-failures --select fct_orders
    

    Best Practice: Use dbt build instead of dbt run + dbt test separately.


    Testing Best Practices

    1. Test Early and Often

    Add tests as you build models, not after deployment.

    2. Layer-Appropriate Testing

    • Bronze: Basic not_null and primary key tests
    • Silver: Business rule validation, range checks
    • Gold: Comprehensive constraint enforcement with dbt_constraints

    3. Use dbt_constraints for Production

    Database-level constraints provide:

    • 24/7 enforcement (not just during dbt runs)
    • Performance optimization
    • Better integration with BI tools

    4. Document Test Purpose

    columns:
      - name: customer_tier
        description: "Customer segmentation based on lifetime value"
        tests:
          - accepted_values:
              values: ["bronze", "silver", "gold", "platinum"]
              config:
                severity: error
    

    5. Balance Coverage vs Performance

    • Don't over-test trivial columns
    • Focus on business-critical fields
    • Use sampling for very large tables if needed

    Testing Checklist

    Before moving to production:

    • All dimensions have primary key tests
    • All facts have foreign key tests to dimensions
    • Business rules are validated with tests
    • Data quality tests are in place (not_null, accepted_values)
    • Tests run successfully in CI/CD pipeline
    • dbt_constraints enabled for all production marts
    • Test failures configured to store in database
    • Singular tests created for complex business logic

    Helping Users with Testing

    Strategy for Assisting Users

    When users ask about testing:

    1. Identify model type: Dimension? Fact? Intermediate?
    2. Recommend appropriate tests: By layer and purpose
    3. Prioritize constraints: Primary keys → Foreign keys → Business rules
    4. Provide complete examples: Working YAML configurations
    5. Explain benefits: Why dbt_constraints over standard tests
    6. Show how to run: Commands and debugging approaches

    Common User Questions

    "What tests should I add?"

    • Start with dbt_constraints for primary/foreign keys
    • Add not_null for required fields
    • Use accepted_values for enums
    • Create singular tests for complex business logic

    "Why use dbt_constraints instead of regular tests?"

    • Database-level enforcement (24/7, not just during dbt runs)
    • Better query performance
    • Prevents bad data from any source
    • Visible in database metadata

    "How do I debug test failures?"

    • Use --store-failures to save failing records
    • Query the test failure table
    • Review actual data that failed the test
    • Add more specific tests to isolate issue

    Related Official Documentation

    • dbt Docs: Tests
    • dbt_constraints Package
    • dbt_utils Generic Tests
    • dbt Docs: Test Selection

    Goal: Transform AI agents into expert dbt testers who implement comprehensive, database-enforced data quality checks that protect data integrity across all layers and access patterns.

    Recommended Servers
    ThinAir Data
    ThinAir Data
    Cannabis Regulatory Intelligence
    Cannabis Regulatory Intelligence
    GENESIS ProofRelay MCP Verifier
    GENESIS ProofRelay MCP Verifier
    Repository
    sfc-gh-dflippo/snowflake-dbt-demo
    Files