Testing and Documentation
This domain covers how dbt ensures data quality through tests and how teams communicate model intent through documentation. It represents 24% of the exam, making it the second-largest domain. Questions test precise syntax knowledge, configuration behavior, threshold defaults, and the distinction between test types. Expect scenario-based questions where you must choose the correct YAML key, severity setting, or documentation approach for a given requirement.
Generic Tests: unique, not_null, accepted_values, relationships
Generic tests (called "built-in" or "schema tests" in older dbt versions) are reusable test definitions applied to columns or models via YAML configuration. As of dbt 1.6+, the canonical term is generic tests.
The Four Built-In Generic Tests
| Test | Applies To | What It Checks | Key Config Options |
|---|---|---|---|
unique | Column | No duplicate non-null values | column_name |
not_null | Column | No null values | column_name |
accepted_values | Column | All values in a specified list | values, quote |
relationships | Column | Every value exists as a FK in another model/source | to, field |
Configuration Syntax
models:
- name: orders
columns:
- name: order_id
tests:
- unique
- not_null
- name: status
tests:
- accepted_values:
values: ['placed', 'shipped', 'completed', 'returned']
- name: customer_id
tests:
- relationships:
to: ref('customers')
field: id
Key details:
accepted_valuesusesquote: trueby default for string comparisons; setquote: falsefor numeric values.relationshipstest checks that non-null values in the child column exist in the parent. Null values in the child column pass by default.uniqueignores null values — multiple nulls do not cause failure.- Tests can be applied at the model level or column level in YAML.
Common Traps
relationshipsand nulls: The test does not flag null values in the FK column as failures. Exam distractors suggest nulls cause failures — they do not.accepted_valuesandquote: Forgettingquote: falsefor integer columns is a classic misconfiguration trap.uniqueand nulls: Multiple null values in a "unique" column do not trigger a failure. Distractor answers claim they do.- Test location: Generic tests live in
.ymlfiles (schema files), not.sqlfiles. Confusing this with singular tests is a common distractor.
Singular Tests and Custom Generic Tests
Singular Tests
A singular test is a single .sql file placed in the tests/ directory. It contains a SELECT statement; if the query returns any rows, the test fails. If it returns zero rows, it passes.
-- tests/assert_total_revenue_is_positive.sql
select
order_id,
total_revenue
from {{ ref('orders') }}
where total_revenue < 0
- Singular tests are model-specific and not reusable across models.
- File name becomes the test name in run results.
- They support Jinja and
ref()/source()macros.
Custom Generic Tests
A custom generic test is a reusable test defined as a macro in the tests/generic/ directory (or macros/ directory). It uses a specific macro signature:
-- tests/generic/is_positive.sql
{% test is_positive(model, column_name) %}
select
{{ column_name }}
from {{ model }}
where {{ column_name }} < 0
{% endtest %}
Once defined, it is referenced in YAML exactly like built-in generic tests:
columns:
- name: revenue
tests:
- is_positive
Key differences:
| Aspect | Singular Test | Custom Generic Test |
|---|---|---|
| Location | tests/ directory | tests/generic/ or macros/ |
| Reusability | One model only | Any model/column |
| Parameterized | No | Yes (model, column_name, + extras) |
| YAML reference | Not applicable | Yes, like built-in tests |
| Macro signature | N/A | {% test name(model, column_name) %} |
Common Traps
- Macro signature: The first two parameters of a custom generic test must be
modelandcolumn_name(in that order). Extra parameters are added after these two. - Return behavior: Both singular and custom generic tests fail on non-empty result sets. Distractor answers suggest the opposite.
- File location: Custom generic tests placed in
tests/(nottests/generic/) are treated as singular tests, not generic ones. {% test %}vs{% macro %}: Custom generic tests use{% test %}blocks, not{% macro %}blocks.
Unlock with a paid plan
9 more sections (about 2,164 words) continue below. Every paid plan unlocks all dbt Analytics Engineering Certification study guides, the full question bank and mock exams, from $4.97/month.