Skip to content

feat(engine): named test definitions — define a check once, apply by name across models#919

Merged
hugocorreia90 merged 1 commit into
mainfrom
feat/named-tests
Jun 17, 2026
Merged

feat(engine): named test definitions — define a check once, apply by name across models#919
hugocorreia90 merged 1 commit into
mainfrom
feat/named-tests

Conversation

@hugocorreia90

Copy link
Copy Markdown
Contributor

What

Reusable named data-quality tests — the declarative analogue of dbt's generic tests (C3). Define an assertion once in models/test_definitions.toml and apply it by name across many models/columns, instead of inlining the same [[tests]] block everywhere.

# models/test_definitions.toml
[positive_amount]
type = "expression"
expression = "amount > 0"

[known_status]
type = "accepted_values"
column = "status"            # default column
values = ["pending", "shipped", "delivered"]

# models/fct_orders.toml
[[tests]]                    # inline tests still work
type = "unique"
column = "order_id"

[[use_test]]                 # apply a named definition
name = "positive_amount"
column = "amount"

[[use_test]]
name = "known_status"        # uses the definition's default column
severity = "warning"

Design

  • References resolve into ordinary TestDecls at load and append to inline [[tests]], so they execute identically through rocky test — no change to the test-execution path.
  • An unknown [[use_test]] name fails the load (ModelError::UnknownTest), so a typo can't silently drop a check.
  • Loading rides a side-loader (load_test_definitions_from_dir). Resolution generalizes the config-group threading (from feat(engine): config groups — one definition fans out routing + strategy to N models #917) — the groups-only param becomes a shared ModelLoadContext { groups, test_defs }; *_with_groups*_with_context; bare load_model_pair/parse_model_inline pass an empty context. Zero ModelConfig churn, no output-schema change (verified: no codegen/schema drift).
  • Wired through both loaders the compiler uses — .sql (load_models_from_dir) and .rocky (salsa) — each with a regression test, and verified end-to-end through rocky compile (valid references resolve; unknown ones error).

Tests

rocky-core: applied-by-reference (default column + severity), column-override + inline coexistence, unknown-name error. rocky-compiler: .rocky model resolves a named test through the salsa loader. Full suites green (1357 core + 325 compiler).

Documented in concepts/data-quality-checks.md.

cargo fmt + clippy --all-targets clean; no codegen/schema drift.

…name across models

Adds reusable named data-quality tests (the declarative analogue of dbt's
generic tests). A `models/test_definitions.toml` defines `name -> { type + params
+ optional default column }`; a model applies one with a `[[use_test]]` block,
binding/overriding the column, severity, and filter at the use site:

    # models/test_definitions.toml
    [positive_amount]
    type = "expression"
    expression = "amount > 0"

    # models/fct_orders.toml
    [[use_test]]
    name = "positive_amount"
    column = "amount"

References resolve into ordinary `TestDecl`s at load and are appended to any
inline `[[tests]]`, so they execute identically through `rocky test` — no
change to the test-execution path. An unknown reference fails the load
(`ModelError::UnknownTest`), so a typo can't silently drop a check.

Loading rides a side-loader (`load_test_definitions_from_dir`). Resolution
generalizes the config-group threading from a `groups`-only param into a shared
`ModelLoadContext { groups, test_defs }`: the `*_with_groups` loaders become
`*_with_context`, and the bare `load_model_pair`/`parse_model_inline` pass an
empty context — zero `ModelConfig` churn, no output-schema change. Wired through
both the `.sql` loader (`load_models_from_dir`) and the `.rocky` salsa loader,
each with a regression test, and verified end-to-end through `rocky compile`
(valid references resolve; unknown ones error).

Documented in concepts/data-quality-checks.md.
@hugocorreia90 hugocorreia90 merged commit 5e57852 into main Jun 17, 2026
13 checks passed
@hugocorreia90 hugocorreia90 deleted the feat/named-tests branch June 17, 2026 22:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant