Docs

Golden tests on DuckDB

How fixtures and expected outputs prove a pipeline on your machine before deploy, when the tests run, and what they do not prove.

Updated Oct 23, 2026

Docs menu · 25 pagesGolden tests on DuckDB

Status

In private development. Early access by invitation.

On this page

A golden test runs a pipeline on a fixed input and compares its output with an expected output. In Emolysis, golden tests are the gate between writing a pipeline and deploying it: a red test sends the agent back to the template, and the agent deploys only after a green run.

What a golden test contains

  • Input fixtures: small tables, usually Parquet, that stand in for the source. They are built to include the hard cases for the shape, not just the happy path.
  • Expected output: the exact table the pipeline should produce from those inputs.
  • The comparison: row for row and column for column. A missing row, an extra row or a changed value fails the test.

Some shapes need more than one run. The SCD Type 2 test, for example, feeds three runs in which an attribute changes, and the Incremental append test feeds two runs whose inputs overlap.

A worked example

Take the SCD Type 2 test for a customer table. The column names here are illustrative. Two runs feed the pipeline:

Runcustomer_idregion
17North
27South

The expected output keeps both versions, with a validity range for each and exactly one current row:

customer_idregionvalid_fromvalid_tois_current
7North2026-01-012026-02-01false
7South2026-02-01true

If a template closed the old row but left the new one out, or left two rows current, the comparison fails and the agent has to fix the fill. The real fixture feeds three runs, and it also checks a change to or from null, which a plain equals comparison would miss.

Why DuckDB

DuckDB runs on your machine, starts instantly and needs no cluster. A golden test takes seconds and spends no warehouse compute, so it is practical to run the tests on every save. DuckDB is the judge: the expected outputs are checked against it, and the same transformation is then translated into your platform's dialect for deployment. See the DuckDB platform page.

When the tests run

WhenWhat runs
Each pipeline the agent writesPlatform lint rules, then the golden tests on DuckDB
Before deployA dry run that writes the deployment files for review
Every pull requestLint and golden tests, with emo check in your CI (the GitHub App is planned)

Your own fixtures

The library templates ship with their own fixtures. For your pipelines, Emolysis adds fixtures to tests/ in your project, and you can add cases of your own, such as a known bad row that once broke production.

Keep fixtures synthetic. They are committed to your repository and run in CI, so anything in them is visible to everyone with access to the repository and to the CI that runs the checks. A sample from your real data is useful for looking at results, but it does not belong in tests/.

Real data, too

Golden tests prove the logic on known cases. To see the result on your own data, you can pull a small sample of the real tables into the project's local lakehouse and run the pipeline on it, still on DuckDB. Reading that sample is a query on your platform; the run itself is local. See Projects and emolysis.yml.

On the real platform

DuckDB proves the logic; the platform proves the rendering. Before a library template is marked green for a platform, its cases must also pass on that platform. A template that passes on DuckDB only is marked yellow. See Templates and slots.

What golden tests do not prove

A green golden test is a strong signal, not a guarantee. It does not cover:

  • Permissions and configuration on your platform. A grant that is missing in Unity Catalog fails at deploy, not in a DuckDB test. See Troubleshooting.
  • Performance and cost at your data volume. Fixtures are small. The cost note and the pull request cost estimate address cost; they do not replace watching the first runs.
  • Data you did not think of. The fixtures include the hard cases for the shape. Your source can still surprise you, which is why you can add cases of your own and why data quality tests on real data remain useful.
  • Behavior that differs between DuckDB and your platform. The dialect translation and the platform lint rules exist to narrow this gap, and the platform run that a library template needs before it is marked green is there to catch what remains.

Golden test, idempotency and data contract in the glossary.