Open-Source Wikis

/

DuckDB

/

How to contribute

/

Testing

duckdb/duckdb

Testing

DuckDB tests are dominated by the sqllogictest format. C++ tests are reserved for things SQL cannot express. The runner is test/unittest, built as part of every standard build.

Running tests

# Fast unit tests (~minutes). Default for local iteration.
make unit
# or directly
build/reldebug/test/unittest

# Single test file
build/reldebug/test/unittest test/sql/order/test_limit.test

# Single test by name (use the # name: from the file)
build/reldebug/test/unittest "Test LIMIT keyword"

# Everything, including .test_slow (~hour)
build/reldebug/test/unittest "*"
make allunit

# Run with a specific working directory or storage version
build/reldebug/test/unittest --test-config test/configs/<config>.json

The runner entry point is test/unittest.cpp and the framework is the sqllogictest runner shipped in the engine.

Sqllogictest format

Tests live under test/sql/<topic>/<test_name>.test. A minimal example:

# name: test/sql/order/test_limit.test
# description: Test LIMIT keyword
# group: [order]

statement ok
CREATE TABLE test (a INTEGER, b INTEGER);

statement ok
INSERT INTO test VALUES (11, 22), (13, 24), (12, 23);

query I
SELECT a FROM test ORDER BY a LIMIT 1
----
11

statement error
SELECT a FROM test LIMIT a
----
<REGEX>:Binder Error:.*not found.*

Directives:

Directive Meaning
statement ok The next SQL statement must succeed.
statement error The next SQL statement must fail. The expected error message follows after ---- (a literal string, or <REGEX>: followed by a regex).
query I, query II, query IIII Query returning N columns. The letter is the column type tag (I = integer, R = real, T = text).
---- Separates query from expected result rows.
require <name> Skip the test unless an extension or feature is loaded (e.g., require parquet).
require-env VAR Skip the test unless VAR is set.
loop, endloop Run a block N times with a substitution variable.
mode skip / mode unskip Disable / enable a block.
concurrentloop Run N copies in parallel — for stress tests.

Test naming:

  • *.test — runs in make unit.
  • *.test_slow — runs only in make allunit and on nightly CI. Use this for tests that take more than a few seconds.

The full reference is at test/README.md and https://duckdb.org/dev/testing.

When to write a C++ test

Use test/api/ only when SQL cannot express the test:

  • Multi-connection concurrency (test/api/test_capi.cpp has examples).
  • Low-level C API behavior.
  • Memory/leak tests (e.g., test/memoryleak/).
  • Fuzzers (test/fuzzer/, test/ossfuzz/).

The C++ tests are written with Catch2 (third_party/catch/).

Categories

Path Purpose
test/sql/ The bulk of the test surface — 4,000+ files organized by topic (joins, types, window functions, subqueries, …).
test/api/ C/C++ API tests.
test/parquet/, test/arrow/, test/csv_scanner/ File-format tests that don't fit cleanly into test/sql.
test/storage/ Storage format and recovery tests.
test/bwc/ Backward-compatibility tests against pinned storage versions.
test/persistence/ Persistence and crash-recovery tests.
test/optimizer/ Plan-shape tests using EXPLAIN.
test/fuzzer/, test/ossfuzz/ Fuzzing harnesses.
test/memoryleak/ Long-running tests that detect leaks under stress.
test/sqlite/ The SQLite logic test corpus, kept compatible.
test/sqlserver/ A subset of SQL Server's logic tests.

Running a benchmark

Benchmarks are not unit tests but live in the same repository:

BUILD_BENCHMARK=1 BUILD_TPCH=1 make
./build/release/benchmark/benchmark_runner --help

See benchmark/README.md for the details.

Coverage

scripts/coverage_check.sh runs lcov over a debug build. CI exercises this via the coverity.yml workflow. Aim for high coverage in make unit; not all paths can be exercised without slow tests, but visible branches in your change should have at least one passing case.

Common testing tips

  • Always test with multiple types — numerics (INTEGER, BIGINT, DECIMAL), strings, dates, and at least one nested type (LIST, STRUCT, MAP).
  • Add an error test. The DuckDB error path is part of the contract.
  • Reproduce a bug as a .test first, fix it, watch the test go green.
  • For optimizer changes, add a mode optimization_* block or use EXPLAIN matching to assert plan shape.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Testing – DuckDB wiki | Factory