Running & Writing Tests
Relevant source files
The following files were used as context for generating this wiki page:
Testing within the dbt-adapters monorepo is divided into three primary categories: code quality checks, unit tests, and integration (functional) tests. Because the repository is a monorepo, tests must generally be executed from within a specific package directory rather than the repository root. The framework utilizes hatch for environment management and pytest as the underlying test runner.
Sources: CONTRIBUTING.md:120-124, AGENTS.md:32-34, CLAUDE.md:27-30
Testing Infrastructure and Environment
Each adapter package (e.g., dbt-postgres, dbt-redshift) contains its own pyproject.toml and hatch.toml. To run tests, developers must first initialize the development environment using hatch run setup. This installs the package in editable mode and sets up necessary testing dependencies, including pre-commit hooks.
Environment Configuration
Integration tests require a live database connection. Configuration is managed via a test.env file (templated from test.env.example) located in the package root. This file contains the credentials needed for the adapter to connect to its target platform.
Sources: CONTRIBUTING.md:46-55, AGENTS.md:24-30, AGENTS.md:46-48
The diagram above shows the typical workflow for preparing a package environment for testing.
Sources: CONTRIBUTING.md:47-55, AGENTS.md:48
Test Categories
Code Quality Checks
Code quality checks are repository-wide and include linting, formatting, and type checking. These tools ensure consistency across the monorepo.
| Tool | Purpose | Command |
|---|---|---|
| Black | Code formatting | hatch run code-quality |
| Flake8 | Linting | hatch run code-quality |
| MyPy | Static type checking | hatch run code-quality |
| Pre-commit | Git hooks for local checks | pre-commit run --all-files |
Sources: CONTRIBUTING.md:131-137, AGENTS.md:38-40, CLAUDE.md:37
Unit Tests
Unit tests verify Python logic without requiring a live database connection. These tests are located in tests/unit/ within each package. They must be executed from the specific package directory.
- Run all unit tests:
hatch run unit-tests - Run specific file:
hatch run unit-tests tests/unit/test_file.py - Run specific method:
hatch run unit-tests tests/unit/test_file.py::ClassName::test_method -v
Sources: CONTRIBUTING.md:141-150, AGENTS.md:44-52, CLAUDE.md:40-41
Integration (Functional) Tests
Integration tests execute against a live database to verify SQL macros, connection handling, and relation management. They are found in tests/functional/.
- Standard Execution:
hatch run integration-tests - Flaky Tests (Redshift):
hatch run integration-tests-flaky(runs sequential execution for unstable tests). - Spark Profiles:
dbt-sparksupports specific profiles likeapache_sparkordatabricks_sql_endpointusing the--profileflag.
Sources: CONTRIBUTING.md:154-156, AGENTS.md:58-64, dbt-spark/CONTRIBUTING.md:16-24
Writing Tests with dbt-tests-adapter
The dbt-tests-adapter package provides a shared suite of reusable test cases. This ensures that all adapters adhere to standard dbt behaviors.
The Inheritance Pattern
Developers write new tests by inheriting from "Base" classes provided by dbt-tests-adapter. These classes define the logic, and the adapter developer only needs to provide the specific configuration or data types for their platform.
from dbt.tests.adapter.basic import BaseSimpleMaterializations
class TestSimpleMaterializations(BaseSimpleMaterializations):
# Inherits standard test logic for tables/views
pass
Sources: AGENTS.md:68-75, dbt-tests-adapter/README.md:38-45
Core Test Suites
dbt-tests-adapter categorizes tests into "Basic" and "Optional":
| Category | Description | Example Base Classes |
|---|---|---|
| Basic | Essential functionality every adapter must pass. | BaseSimpleMaterializations, BaseIncremental, BaseSnapshotCheck, BaseDocsGenerate |
| Optional | Second-order functionality common across many plugins. | BaseMaterializedView, BasePythonModel, BaseGrants, BaseConstraints |
Sources: dbt-tests-adapter/README.md:17-30, CLAUDE.md:65-72
Test Data Fixtures
Tests often use Python variables to define dbt project files (SQL, YAML, CSV) dynamically. The write_project_files utility is frequently used to set up the test environment.
# Example fixture from dbt-tests-adapter
models__model_sql = """
{{ config(materialized='view') }}
select * from {{ ref('seed') }}
"""
Sources: dbt-tests-adapter/src/dbt/tests/adapter/basic/test_docs_generate.py:91-98
Test Architecture
The following sequence diagram illustrates how an integration test interacts with the adapter and the database.
This diagram depicts the flow of a standard functional test inheriting from the shared test suite.
Sources: CLAUDE.md:52-61, dbt-tests-adapter/src/dbt/tests/adapter/basic/test_docs_generate.py:304-320
Specialized Testing Tools
Dagger (dbt-spark)
The dbt-spark package uses Dagger to orchestrate its test suite. This allows the tests to launch virtual containers to provide the necessary Spark environments for testing against various profiles.
Sources: dbt-spark/CONTRIBUTING.md:7-11
Changie
While not a functional test tool, changie is used to enforce "Code Quality" for documentation. Every pull request requires a new changelog entry created via changie new.
Sources: CONTRIBUTING.md:167-175, AGENTS.md:92-96
Summary
Testing in the dbt-adapters project relies on a strictly inherited structure from dbt-tests-adapter to maintain consistency across different database platforms. By utilizing hatch for environment isolation and standardized "Base" classes for functional verification, the monorepo ensures that all first-party and community adapters meet a baseline of quality and compatibility.