Skip to main content
On this page

Kater CLI Build and check test

kater test

Runs the tests of your shared models, and says which ones pass and which ones fail.

A test is a fixed question with a fixed answer: these fields, over these dates, return exactly these rows. Run the tests after you change a model, or after new data loads, so that no number moves by surprise. It runs on the warehouse unless you add --local or --compile-only. Its subcommands write draft tests, list the tests and check a model’s readiness. kater new test adds one test. See Tests.

Commands

CommandWhat it does
kater test updateMark a draft test as checked.
kater test listList tests and how each one last ran.
kater test snapshotCopy the rows your tests read to this machine.
kater test readinessSay whether a model is ready to hand off.
kater test generateWrite a starting set of draft tests for a model.

Examples

Terminal window
# Run every test of the connection that you can read
kater test --select connection:snowflake_prod_connection
# Run the tests of the shared ad_reporting model
kater test --select semantic.ad_reporting
# Run the tests that have the tag team=marketing
kater test --select tag:team=marketing
# Run one test, and print the SQL that each of its paths ran
kater test --select july_2026_totals_by_platform --show-sql
# Run the merge check: only the tests that a change since main could move
kater test --select state:modified+ --state git:main --stale
# Keep the new rows of the failing tests, after a change that you meant to make
kater test --select semantic.ad_reporting --update
# Write five draft tests for the shared ad_reporting model
kater test generate --model semantic.ad_reporting
# List the model's tests and how each one last ran
kater test list --model semantic.ad_reporting
# Check whether the model is ready to hand off
kater test readiness --model semantic.ad_reporting

Options

OptionDescription
-s, --select <selection>The tests to run. A model, such as semantic.ad_reporting, selects its tests: the shared layer’s, and each person’s that you can read. A test file, or path:FILE, selects the tests in that file, and a test’s name selects that test. tag:team=marketing selects the tests that have this tag in their tags. See Selecting models. You can give it more than one time.
--exclude <selection>The tests to leave out, in the same words as --select. You can give it more than one time.
--state <state>What state:modified and state:new compare with: a folder that holds an earlier manifest.json, or git:REF, such as git:main.
--localRuns on the local copy that kater test snapshot made, with no warehouse credentials. A fixture test runs on its own rows. A test that the copy does not answer is left for the warehouse.
--compile-onlyCompiles every test and runs nothing on the warehouse. It reports each test as unchanged or stale against its last pass. It checks a refused test in full.
--staleRuns only the tests whose compiled SQL or expected answer changed since their last pass, or that never passed.
--updateRecords new rows for each failing rows test whose paths agree, and prints each number that moved. Use it after a change that you meant to make. It never changes a same_as or refused test. You cannot use it with --local.
--show-sqlPrints the Kater SQL and the warehouse SQL that each path ran.

It also takes the global options --json, --kater-root, --scope and --help.

Where tests live

Each model’s tests are in one file, named after the model. A test file can be in one of three places in the connection’s folder:

WhereWhose tests
modeling/kater_objects/tests/<model>.sqlThe shared layer’s tests. Everyone who reads the model reads them. Only these count toward readiness.
users/<email>/tests/<model>.sqlYour own tests. A new test goes here unless you add --shared.
workspaces/<workspace>/tests/<root>.sqlThe tests of a connection workspace’s root, with its parameters and filters.

What a test holds

  • A question. It asks its question as field picker selections, as hand-written Kater SQL, or both. Kater checks each one.
  • An expected answer. It expects exact rows, the same answer as another query (same_as), or the code that the compiler refuses the SQL with (refused).
  • Optional keys. as_of sets the day that the test takes as today, for relative dates. given gives a fixture’s rows in place of the warehouse’s. inputs gives a connection workspace’s root its parameter values and filters.

Which tests run

With no --select, it runs every test of the connection that you are in, or of your only connection, that you can read. That is the shared layer’s tests, each connection workspace’s tests, your own, and any that someone shared with you. A run reads the tests of one connection only. When a selection reaches tests of more than one connection, the run stops: add connection:NAME to the selection, such as --select connection:snowflake_prod_connection,tag:team=marketing.

kater test and kater test snapshot take the connection from --select. The other test commands take --connection. Without them, Kater uses the folder of the Files terminal. Or else it uses the one connection whose shared models include --model, or your only connection.

What it prints

Each test prints a line when it starts and a line when it ends, as kater build shows them. Tests that run on the warehouse run side by side, so their lines can end in a different order. The run ends with its time, a block for each test that failed, and a summary. It writes target/run_results.json.

  • PASS and FAIL. The test returned the expected answer, or it did not. FAIL 4 counts the values that differ.
  • ERROR. The test could not run, or it is not written correctly.
  • WARN. The test has no answer yet, such as a same_as test with no native SQL. With --compile-only or --stale, a test whose SQL moved since its last pass also warns.
  • PASS with --compile-only or --stale. The test’s SQL did not move since its last pass, so it did not run.

With --show-sql or --update, a list follows the summary: each test with the SQL that it ran, or each number that --update recorded again. With --json, the answer is the run’s own JSON, with each test in items.

Columns compare by position. Numbers compare at the decimal places that their format shows, such as cents. When a test fails and its SQL did not change since its last pass, the message says that the data changed. A draft with no answer yet keeps the rows of its first run that returns rows.

The merge check

--select state:modified+ --state git:main --stale runs only the tests that a change since main could reach: the tests of each file that this branch changed, and of each model that reads those files. Of those, it runs only the tests whose compiled SQL moved since their last pass. --state git:main reads git in your local copy: the files committed since this branch left main, changed but not committed, or new. The other tests count as unchanged.

Results and exit codes

  • Where results go. In your own terminal, each warehouse run is recorded in .kater/test-status/ in your content root. A local run is recorded apart, and it never makes a test pass or stale. kater test list and kater test readiness read these records.
  • Exit codes. 0 when no test failed, 1 when a test failed or could not run, and 2 for a command that is not valid. A draft with no answer yet does not fail the run. With --compile-only, a stale test does not fail the run.

See also