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>.jsonThe 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 inmake unit.*.test_slow— runs only inmake allunitand 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.cpphas 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 --helpSee 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
.testfirst, fix it, watch the test go green. - For optimizer changes, add a
mode optimization_*block or useEXPLAINmatching to assert plan shape.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.