Test Utilities & Containers
Relevant source files
The following files were used as context for generating this wiki page:
- crates/dbt-metricflow/tests/metricflow_compat.rs
- crates/dbt-parser/src/tests.rs
- crates/dbt-parser/src/resolve/resolve_tests/resolve_data_tests.rs
- crates/dbt-parser/src/resolve/resolve_tests/persist_generic_data_tests.rs
- crates/dbt-docs-server/src/handlers/tests.rs
- crates/dbt-test-containers/Cargo.toml
Test Utilities & Containers provide the infrastructure required to validate the dbt Core v2.0 transformation logic, Jinja rendering, and MetricFlow integration. The system encompasses isolated database environments using ADBC-driven DuckDB, comprehensive mocking of Jinja environments, and the synthesis of generic test assets.
This module ensures that parsing, compilation, and execution results remain consistent across different database dialects and project configurations. It specifically supports differential testing of semantic manifests and the persistence of generic data tests for documentation and execution purposes.
Isolation and Environment Setup
The testing infrastructure relies on isolated environments to prevent state leakage between test cases. This is achieved through memory-resident databases and mock Jinja configurations.
DuckDB ADBC Wrapper
For semantic and metric testing, a specialized DuckDB wrapper utilizes the Arrow Database Connectivity (ADBC) protocol. This allows tests to execute SQL against an in-memory database without external dependencies. The DuckDb struct manages connections and executes updates or queries, returning results as Arrow RecordBatch objects for high-performance data verification.
The diagram shows the lifecycle of a containerized memory database used during the MetricFlow compatibility tests.
Sources: crates/dbt-metricflow/tests/metricflow_compat.rs:26-64
Mock Jinja Environment
Unit and integration tests for the parser use the setup_test_env function to initialize a JinjaEnv. This environment mocks a Postgres database configuration, including standard dbt quoting rules and invocation arguments. This setup allows for the rendering of SQL blocks that include macros like ref(), source(), and config() without a live warehouse.
Sources: crates/dbt-parser/src/tests.rs:77-118
Generic Test Synthesis and Hashing
dbt Core v2.0 synthesizes generic tests (e.g., unique, not_null) by generating SQL files and unique identifiers based on metadata hashes.
Unique ID Generation
Unique IDs for generic tests are constructed using a specific convention to ensure parity with dbt-core (Python). The process involves hashing a string composed of the Fully Qualified Name (FQN) and a Python-like representation of the test metadata.
| Component | Description |
|---|---|
| Hash String | fqn_name + repr(test_metadata) |
| Hash Algorithm | MD5 |
| Suffix | Last 10 characters of the MD5 hex digest |
| Final ID | test.<package>.<fqn_name>.<suffix> |
Sources: crates/dbt-parser/src/resolve/resolve_tests/resolve_data_tests.rs:80-100
Test Name Truncation
To comply with database identifier limits, synthesized test names are truncated to 63 characters. If a name exceeds this limit, the system preserves the first 30 identifying characters and appends a 32-character hash of the full content.
Logic flow for ensuring test names remain valid database identifiers.
Sources: crates/dbt-parser/src/resolve/resolve_tests/persist_generic_data_tests.rs:564-585
Differential Testing and Compatibility
The project includes a differential testing harness designed to compare the Rust implementation against reference implementations.
MetricFlow Compatibility Harness
This harness builds a semantic manifest from fixtures, populates DuckDB with snapshot data, and executes queries. It reports a scorecard comparing the Rust-generated SQL output against expected row counts and scalar values.
Key verification steps include:
- Compilation: Verifying that the query spec produces valid DuckDB or Snowflake SQL.
- Execution: Running the SQL against the ADBC DuckDB wrapper.
- Scalar Comparison: Ensuring the final metric values match reference results within a 0.01 epsilon.
Sources: crates/dbt-metricflow/tests/metricflow_compat.rs:913-960
Documentation and Execution Info
The dbt-docs-server provides endpoints to retrieve test metadata and execution results, which are stored as Parquet artifacts.
Test Response Structure
Tests are categorized into Data (generic/singular) and Unit tests. Data tests are joined against dbt.test_metadata to retrieve severity and column information, while Unit tests carry inline fixtures.
| Field | Source Table | Description |
|---|---|---|
status | dbt_rt.run_results | The outcome of the last test run (pass, fail, error). |
error | dbt_rt.run_results | Error message populated if status indicates failure. |
kwargs | dbt.test_metadata | JSON arguments passed to the generic test macro. |
given | dbt.unit_tests | Input fixtures for unit tests. |
Sources: crates/dbt-docs-server/src/handlers/tests.rs:32-110
Execution Information Flow
Sequence of events for retrieving execution status and error messages for a specific test.
Sources: crates/dbt-docs-server/src/handlers/tests.rs:244-275
Summary
The Test Utilities & Containers module provides the essential toolkit for ensuring dbt Core v2.0 reliability. By integrating ADBC-driven DuckDB environments, strict hashing protocols for test identifiers, and differential testing harnesses, the project guarantees that transformation logic remains accurate across dialects. The system's ability to synthesize and persist tests ensures that data quality checks are both executable and well-documented within the dbt ecosystem.