Skip to content

Manifest Checks: Tests#

Note

The below checks require manifest.json to be present.

Functions:

Name Description
check_test_has_meta_keys

The meta config for data tests must have the specified keys.

check_test_has_tags

Data tests must have the specified tags.

check_test_has_meta_keys #

The meta config for data tests must have the specified keys.

Rationale

The meta field on data tests is a flexible store for operational metadata such as ownership, severity context, or ticket references. Enforcing required keys ensures that every test carries the information needed to triage failures quickly — for example, knowing which team owns a failing test or what SLA it is tied to — without relying on tribal knowledge or documentation that falls out of sync.

Parameters:

Name Type Description Default
keys NestedDict

A list (that may contain sub-lists) of required keys.

required

Receives at execution time:

Name Type Description
test TestNode

The TestNode object to check.

Other Parameters (passed via config file):

Name Type Description
description str | None

Description of what the check does and why it is implemented.

exclude str | None

Regex pattern to match the test path. Test paths that match the pattern will not be checked.

include str | None

Regex pattern to match the test path. Only test paths that match the pattern will be checked.

severity Literal[error, warn] | None

Severity level of the check. Default: error.

Example(s):

manifest_checks:
    - name: check_test_has_meta_keys
      keys:
        - owner

Source code in src/dbt_bouncer/checks/manifest/check_tests.py
@check
def check_test_has_meta_keys(test, *, keys: NestedDict):
    """The `meta` config for data tests must have the specified keys.

    !!! info "Rationale"

        The `meta` field on data tests is a flexible store for operational metadata such as ownership, severity context, or ticket references. Enforcing required keys ensures that every test carries the information needed to triage failures quickly — for example, knowing which team owns a failing test or what SLA it is tied to — without relying on tribal knowledge or documentation that falls out of sync.

    Parameters:
        keys (NestedDict): A list (that may contain sub-lists) of required keys.

    Receives:
        test (TestNode): The TestNode object to check.

    Other Parameters:
        description (str | None): Description of what the check does and why it is implemented.
        exclude (str | None): Regex pattern to match the test path. Test paths that match the pattern will not be checked.
        include (str | None): Regex pattern to match the test path. Only test paths that match the pattern will be checked.
        severity (Literal["error", "warn"] | None): Severity level of the check. Default: `error`.

    Example(s):
        ```yaml
        manifest_checks:
            - name: check_test_has_meta_keys
              keys:
                - owner
        ```

    """
    missing_keys = find_missing_meta_keys(
        meta_config=test.meta, required_keys=keys.model_dump()
    )
    if missing_keys:
        fail(
            f"`{test.unique_id}` is missing the following keys from the `meta` config: {[x.replace('>>', '') for x in missing_keys]}"
        )

check_test_has_tags #

Data tests must have the specified tags.

Rationale

Tags allow teams to organise tests into logical groups (e.g. critical, nightly, schema-only) and run subsets selectively with dbt test --select tag:critical. Without enforced tagging, it becomes difficult to prioritise test failures, run fast CI checks, or set up tiered alerting based on test severity.

Parameters:

Name Type Description Default
criteria Literal[any, all, one] | None

Whether the test must have any, all, or exactly one of the specified tags. Default: all.

'all'
tags list[str]

List of tags to check for.

required

Receives at execution time:

Name Type Description
test TestNode

The TestNode object to check.

Other Parameters (passed via config file):

Name Type Description
description str | None

Description of what the check does and why it is implemented.

exclude str | None

Regex pattern to match the test path. Test paths that match the pattern will not be checked.

include str | None

Regex pattern to match the test path. Only test paths that match the pattern will be checked.

severity Literal[error, warn] | None

Severity level of the check. Default: error.

Example(s):

manifest_checks:
    - name: check_test_has_tags
      tags:
        - critical

Source code in src/dbt_bouncer/checks/manifest/check_tests.py
@check
def check_test_has_tags(test, *, criteria: str = "all", tags: list[str]):
    """Data tests must have the specified tags.

    !!! info "Rationale"

        Tags allow teams to organise tests into logical groups (e.g. `critical`, `nightly`, `schema-only`) and run subsets selectively with `dbt test --select tag:critical`. Without enforced tagging, it becomes difficult to prioritise test failures, run fast CI checks, or set up tiered alerting based on test severity.

    Parameters:
        criteria (Literal["any", "all", "one"] | None): Whether the test must have any, all, or exactly one of the specified tags. Default: `all`.
        tags (list[str]): List of tags to check for.

    Receives:
        test (TestNode): The TestNode object to check.

    Other Parameters:
        description (str | None): Description of what the check does and why it is implemented.
        exclude (str | None): Regex pattern to match the test path. Test paths that match the pattern will not be checked.
        include (str | None): Regex pattern to match the test path. Only test paths that match the pattern will be checked.
        severity (Literal["error", "warn"] | None): Severity level of the check. Default: `error`.

    Example(s):
        ```yaml
        manifest_checks:
            - name: check_test_has_tags
              tags:
                - critical
        ```

    """
    resource_tags = test.tags or []
    if criteria == "any":
        if not any(tag in resource_tags for tag in tags):
            fail(f"`{test.unique_id}` does not have any of the required tags: {tags}.")
    elif criteria == "all":
        missing_tags = [tag for tag in tags if tag not in resource_tags]
        if missing_tags:
            fail(f"`{test.unique_id}` is missing required tags: {missing_tags}.")
    elif criteria == "one" and sum(tag in resource_tags for tag in tags) != 1:
        fail(f"`{test.unique_id}` must have exactly one of the required tags: {tags}.")